锁的一些基本概念

  1. 公平锁VS非公平锁

    • 公平锁(Fair):加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得,例如每个线程抢占锁的顺序为先后调用lock方法的顺序依次获取锁,类似于排队吃饭。
    • 非公平锁(Nonfair):加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待,例如每个线程抢占锁的顺序不定,谁运气好,谁就获取到锁,和调用lock方法的先后顺序无关,类似于堵车时,加塞的那些XXXX。

      synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序;
      ReentrantLock 默认的lock()方法采用的是非公平锁,但可以选择公平锁实现的方式。
      public ReentrantLock(boolean fair) //根据参数初始化为公平锁或者非公平锁
      {
      sync = fair ? new FairSync() : new NonfairSync();
      }

  2. Volatile

    • 通过java内存模型(JMM)保证volatile的可见性和有序性。编译器和处理器不会对存在数据依赖关系的操作做重排序,因为这种重排序会改变执行结果。而线程与线程之间使用的是共享变量的副本,副本没有依赖关系导致线程间可能出现重排序的问题;
    • JMM通过java进程之间的通信,控制主内存与每个线程的本地内存之间的交互,来为java程序员提供内存可见性保证;
    • Volatile通过内存屏障保证写的数据即时刷新到主内存,来防止线程间的重排序问题。
  3. 内存屏障的作用:

    • 阻止屏障两边的指令重排序;
    • 强制把写缓冲区/高速缓存中的脏数据等写回主内存,让缓存中相应的数据失效。

    对Load Barrier来说,在读指令前插入读屏障,可以让高速缓存中的数据失效,重新从主内存加载数据;
    对Store Barrier来说,在写指令之后插入写屏障,能让写入缓存的最新数据写回到主内存。

<think>好的,用户想了解和死的概念。首先,我需要从基础开始解释的定义,说明它在多线程或多进程环境中的作用,比如保证资源访问的互斥性。然后,可能需要举一个简单的例子,比如银行转账,来说明为什么需要。 接下来是死的概念,必须提到四个必要条件:互斥、持有并等待、不可抢占、循环等待。这部分需要详细解释每个条件,并结合例子说明。比如,两个线程各自持有一个,同时请求对方持有的,导致互相等待。 然后,根据提供的引用,用户可能希望了解死的常见场景,比如引用[2]提到的三种情况:一线程一、两线程两、M线程N。需要简要说明这些情况,但可能用户更关注基本概念,所以这部分可以点到为止。 此外,用户提供的引用中有关于避免死的策略,比如引用[5]提到的读写和正确的释放方法,还有引用[3]中的预防、避免、检测和恢复方法。这些可以作为解决方案部分的内容,但用户的问题主要是概念性的,所以可能需要简要提及解决方案,但重点放在解释概念上。 需要注意的是,回答要使用中文,数学表达式用$...$,独立公式用$$...$$。比如,在解释死的条件时,可能需要用项目符号列出,但根据示例,不需要复杂的数学公式,可能用简单的例子更合适。 用户可能还希望了解的类型,比如互斥、读写、分布式(引用[4]),但根据问题,重点在概念,所以可以简要提到这些类型,但不过多展开。 最后,生成相关问题时要参考示例,确保问题与主题相关,帮助用户深入理解。比如,死的必要条件,避免方法,实际案例等。 总结回答结构:先定义,再死,接着必要条件,最后解决方案概述。然后生成相关问题。</think>### 与死的概念解析 #### 1. **基本概念** 是计算机科学中用于**控制资源访问**的同步机制,主要解决多线程/多进程环境中**资源竞争**问题。其核心作用是保证**互斥访问**——当一个线程持有时,其他线程必须等待释放才能访问受保护资源[^1][^4]。 例如,在银行转账场景中,若账户A和账户B同时被两个线程操作,使用可以防止同时修改账户余额导致数据错误: ```python lock = threading.Lock() def transfer(account_from, account_to): with lock: # 获取 account_from.balance -= amount account_to.balance += amount ``` #### 2. **死的定义** 死是多个线程/进程因**循环等待资源**而全部无法推进的状态。其本质是**资源分配顺序冲突**,常见于需要同时持有多个的场景[^2][^3]。 例如,线程1持有A并请求B,线程2持有B并请求A,此时双方陷入无限等待: $$ \begin{cases} \text{线程1: } \text{Lock(A)} \rightarrow \text{请求 Lock(B)} \\ \text{线程2: } \text{Lock(B)} \rightarrow \text{请求 Lock(A)} \end{cases} $$ #### 3. **死的四个必要条件**[^1][^3] | 必要条件 | 说明 | 示例场景 | |------------------|-----------------------------|-----------------------------| | **互斥** | 资源只能被独占访问 | 打印机一次只能服务一个打印任务 | | **持有并等待** | 持有资源的同时请求新资源 | 线程持A后请求B | | **不可抢占** | 资源只能由持有者主动释放 | 操作系统无法强制回收已分配的 | | **循环等待** | 等待关系形成闭环 | 线程1等B,线程2等A | #### 4. **典型死场景** - **两线程两**:经典交叉请求(如上述转账案例) - **M线程N**:多个线程形成环形依赖链(如线程1→2→3→1等待链) - **分布式死**:跨系统资源争夺(如微服务调用链中的数据库竞争) #### 5. **解决策略概述** | 方法类型 | 实现手段 | 实例 | |--------------|---------------------------------|-------------------------| | **预防** | 破坏必要条件(如强制按顺序获取) | 统一的获取顺序规则 | | **避免** | 动态检查资源分配安全性(如银行家算法)| 系统拒绝可能导致死的请求 | | **检测恢复** | 定期检测死并终止/回滚进程 | 数据库事务死自动回滚机制 | | **规避设计** | 使用阻塞(如tryLock) | Java的`ReentrantLock.tryLock()` |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值