7.await和signal流程解析

104 阅读1分钟

await整体流程

await整体流程

await 流程

步骤一.进入等待队列

image.png 一开始 Thread-0 持有锁,调用 await方法,进入ConditionObject的addConditionWaiter流程:

创建状态为Node.CONDITION=-2的新Node,并关联 Thread-0,然后加入等待队列尾部。

步骤二.解锁释放所有的锁

image.png

接下来进入 AQS 的 fullyRelease 流程,因为执行await方法需要释放锁。释放同步器上所有的锁,因为是await,有可能有锁重入,所以叫fullyRelease 。

这里也体现了为什么await方法必须要持有锁才能调用,因为不持有锁就没法释放锁。

此时在lock中占有锁的线程Thread-0的持有者owner被置为null。

步骤三.unpark同步队列中下一个节点node

image.png unpark AQS 队列中头结点的下一个节点,竞争锁,假设没有其他竞争线程,那么 Thread-1 竞争成功。

步骤四:自己在等待队列阻塞

image.png

Thread-0 一直park被阻塞。

signal 流程

步骤一.唤醒阻塞在等待队列的节点

image.png

假设 Thread-1 要来唤醒 Thread-0

步骤二.从等待队列出列

image.png

进入 ConditionObject 的 doSignal 流程,取得等待队列中第一个 Node,即 Thread-0 所在 Node

步骤三.进入同步队列

image.png

执行 transferForSignal 流程,将该 Node 加入 AQS 队列尾部,将 Thread-0 的 waitStatus 改为 0,Thread-3的waitStatus 改为 -1,有可能会失败,原因是被打断了 这时就不会加入等待链表。

步骤四.其他线程unpark当前线程,开始获取锁