1.加锁


  1. 先从构造器开始看,默认为非公平锁实现
  2. 没有竞争时,CAS修改state 状态0—>1,设置当前线程为独占线程
  3. 第一个竞争出现时,进入 tryAcquire 逻辑,这时 state 已经是1,结果仍然失败
  4. 接下来进入 addWaiter 逻辑,构造 Node 队列
    • 首次创建,创建两个node节点,双向队列
    • Node 的创建是懒惰的,其中第一个 Node 称为 Dummy(哑元)或哨兵,用来占位,并不关联线程
    • Node 的 waitStatus 状态,0 为默认正常状态
  5. 当前线程进入 acquireQueued 逻辑
    • acquireQueued 会在一个死循环中不断尝试获得锁,失败后进入 park 阻塞
    • 如果自己是紧邻着 head(排第二位),那么再次 tryAcquire 尝试获取锁,当然
      这时 state 仍为 1,失败
    • 进入 shouldParkAfterFailedAcquire 逻辑,将前驱 node,即 head 的waitStatus 改为 -1(有责任唤醒后继节点,进入阻塞队列),这次返回 false
    • shouldParkAfterFailedAcquire 执行完毕回到 acquireQueued ,再次 tryAcquire 尝试获取锁,当然这时state 仍为 1,失败
    • 当再次进入 shouldParkAfterFailedAcquire 时,这时因为其前驱 node 的 waitStatus 已经是 -1,这次返回true
    • 进入 parkAndCheckInterrupt, Thread-1 park,进入阻塞状态

      2.解锁


  1. Thread-0 释放锁,进入 tryRelease 流程,如果成功
  2. 设置 exclusiveOwnerThread 为 null,state = 0
  3. 当前队列不为 null,并且 head 的 waitStatus = -1,进入 unparkSuccessor 流程
  4. 找到队列中离 head 最近的一个 Node(没取消的),unpark 恢复其运行,即为 Thread-1
  5. 回到 Thread-1 的 acquireQueued 流程
    • 如果加锁成功(没有竞争),会设置exclusiveOwnerThread 为 Thread-1,state = 1
    • head 指向刚刚 Thread-1 所在的 Node,该 Node 清空 Thread
    • 原本的 head 因为从链表断开,而可被垃圾回收
  6. 如果这时候有其它线程来竞争(非公平的体现),例如这时有 Thread-4 竞争,若被 Thread-4 抢占
    • Thread-4 被设置为 exclusiveOwnerThread,state = 1
    • Thread-1 再次进入 acquireQueued 流程,获取锁失败,重新进入 park 阻塞