heima并发---并发工具包(3)---条件变量--245

每个条件变量对应一个conditionObject这个对象,这个对象在sync里面的,内部也是维护了一个双向链表的。

await流程和signal流程。

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

这个方法就是线程加入到条件变量的双向链表里面去。

都是假如到队列的尾部的。

heima并发---并发工具包(3)---条件变量--245

可知:

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

接下来:

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

这个方法是当前的节点就是thread-0节点上的所有锁都释放掉,和wait是一样的,包括锁重入的次数。

heima并发---并发工具包(3)---条件变量--245

唤醒等待队列的离头节点最近的下一个节点,竞争。

heima并发---并发工具包(3)---条件变量--245

 

接下来进入park状态,等待被唤醒。

heima并发---并发工具包(3)---条件变量--245

while循环我们不管它。

heima并发---并发工具包(3)---条件变量--245

---245---

signal方法:

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

首先检查调用signal的方法是不是锁的持有者,不是就直接抛出异常。

heima并发---并发工具包(3)---条件变量--245

找条件变量等待队列里面的头的元素,不为空就调用doSignal方法。

注意:链表有多个元素的话也不是随机的去调用,总是调用队首的元素。

进入doSingnal方法:

heima并发---并发工具包(3)---条件变量--245

这个方法主要是使节点在条件变量这个链表断开,重新竞争锁,加入到等待锁的这个链表中。

heima并发---并发工具包(3)---条件变量--245

第一个waiter=第一个waiter的nextWaiter。

指向null,在条件变量这个链表中断开。

进入这个方法:

heima并发---并发工具包(3)---条件变量--245

节点转移到竞争锁的链表,就是等待队列的。转移失败的话唤醒下一个节点。

为什么会转移失败呢?可能会被打断或者取消的。

heima并发---并发工具包(3)---条件变量--245

这里为什么改为0。因为加入到条件变量这个链表中这个状态就变成了-2了。加入到锁的竞争队列里面,总是为0。

进入到这个方法:

heima并发---并发工具包(3)---条件变量--245

进入:

heima并发---并发工具包(3)---条件变量--245

将节点加入到等待队列的尾部。成功了返回前驱节点。

heima并发---并发工具包(3)---条件变量--245

检查前驱节点的状态。改为-1,有责任唤醒链表的下一个元素。

流程分析:

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

源码解析:

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

heima并发---并发工具包(3)---条件变量--245

---246---