Condition 源码分析 (基于Java 8) - 简书
使用ReentrantLock
比直接使用synchronized
更安全,可以替代synchronized
进行线程同步。
但是,synchronized
可以配合wait
和notify
实现线程在条件不满足时等待,条件满足时唤醒,用ReentrantLock
我们怎么编写wait
和notify
的功能呢?
答案是使用Condition
对象来实现wait
和notify
的功能。
Condition
ConditionObject
Condition Queue Node waitStatus
- 初始化值:Node.CONDITION(-2)。
- 线程interrupt时,waitStatus被设置为0,(checkInterruptWhileWaiting)
- signal也会将waitStatus设置为0。通过transferForSignal(Node node)方法。signal/signalAll方法还会将nextWaiter置为null。
- await timeout时也会将waitStatus设置为0
addConditionWaiter
doSignal
doSignalAll
transferForSignal
unlinkCancelledWaiters
一般的节点都会被 signal 唤醒, 从 Condition Queue 转移到 Sync Queue, 而若遇到 interrupt 或 等待超时, 则直接改变 node 的状态(从 CONDITION 变成 0), 并直接放入 Sync 里面, 而不清理Condition Queue 里面的节点, 所以unlinkCancelledWaiters函数做清理工作。
这个是私有方法,查看调用链,仅出现在多个await方法中。所以删除等待队列中cancelled nodes 这个动作只在持有锁且await的前提下出现。
await
fullyRelease
fullyRelease方法仅被await方法调用,说明await方法会释放锁。
cancelAcquire
Acquire失败的时候,需要将当前节点取消。
node.waitStatus = Node.CANCELLED
fullyRelease方法和cancelAcquire方法中都有取消的逻辑。