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

condictionObject相当于Monitor的waitSet。

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

await流程和signal流程。

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

都是加入到队列的尾部的。

可知:

---

看下这个方法:

接下来:

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

这个saveStated是所有的锁重入的次数。

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

进入release方法。

唤醒头结点的下一个节点。

这里unpark就解除阻塞了,进入到acquireQueue得方法继续执行:

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

while循环我们不管它。

---245---

假设这个场景:

Thread-1是锁得持有者,thread-0在条件变量里面等待的。

调用singal的线程必须是锁的持有者。

signal方法:

首先检查调用signal的方法是不是锁的持有者,不是就直接抛出异常,只有owner才有资格去唤醒得。

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

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

进入doSingnal方法,做了哪两件事?第一件事就是在条件变量的队列去掉头,然后把头加到等待队列里面去。

转移失败就找下一个节点。

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

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

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

进入这个方法,节点注意到竞争锁的队列:

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

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

---

进入transferForSingal方法:

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

进入到这个方法:

进入,把节点加到等待队列的尾部。

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

看下前驱结点并改为-1

再来:

再来:进入acquireQueue方法。

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

流程分析:

源码解析:

---246---

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值