Condition 源码分析 (基于Java 8) - 简书

使用ReentrantLock比直接使用synchronized更安全,可以替代synchronized进行线程同步。
但是,synchronized可以配合waitnotify实现线程在条件不满足时等待,条件满足时唤醒,用ReentrantLock我们怎么编写waitnotify的功能呢?
答案是使用Condition对象来实现waitnotify的功能。

Condition

image.png

ConditionObject

image.png

Condition Queue Node waitStatus

  1. 初始化值:Node.CONDITION(-2)。

image.png

  1. 线程interrupt时,waitStatus被设置为0,(checkInterruptWhileWaiting)

image.png

  • signal也会将waitStatus设置为0。通过transferForSignal(Node node)方法。signal/signalAll方法还会将nextWaiter置为null。
  • await timeout时也会将waitStatus设置为0

    addConditionWaiter

    image.png

    doSignal

    image.png

    doSignalAll

    image.png

    transferForSignal

    image.png

    unlinkCancelledWaiters

    一般的节点都会被 signal 唤醒, 从 Condition Queue 转移到 Sync Queue, 而若遇到 interrupt 或 等待超时, 则直接改变 node 的状态(从 CONDITION 变成 0), 并直接放入 Sync 里面, 而不清理Condition Queue 里面的节点, 所以unlinkCancelledWaiters函数做清理工作。

这个是私有方法,查看调用链,仅出现在多个await方法中。所以删除等待队列中cancelled nodes 这个动作只在持有锁且await的前提下出现。
image.png

await

封装当前线程加入
image.png

fullyRelease

fullyRelease方法仅被await方法调用,说明await方法会释放锁。
image.png

cancelAcquire

Acquire失败的时候,需要将当前节点取消。

  1. node.waitStatus = Node.CANCELLED

fullyRelease方法和cancelAcquire方法中都有取消的逻辑。