请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

Condition

1、Condition 对应的等待队列中的节点也是Node类的实例,且字段中的nextWaiter指向等待队列中的下一个节点,那么它字段中的prev,next指向什么?如果分别指向前一个节点和后一个节点,那么它怎么会是单向链表呢?
2、独占锁中使用Condition,当调用Condition.signal()时会唤醒Condition 对应的等待队列中的节点,加入到同步队列中,是先唤醒还是先把节点加入同步队列?此时同步队列中的节点是唤醒的还是阻塞的?

正在回答 回答被采纳积分+3

1回答

Jimin 2019-02-13 11:50:09

你好,先看一下Condition的关系图:

https://img1.sycdn.imooc.com//szimg/5c6392f000014e6614280798.jpg

Condition虽然和AQS组件有关,但不是基于AQS做的实现,从上面的关系图上可以看的很清楚。


接下来总结一下 Condition 执行 await 和 signal 的过程:

首先,线程如果想执行 await 方法,必须拿到锁,在 AQS 里面,抢到锁的一般都是 head,然后 head 失效,从队列中删除。在当前线程(也就是 AQS 的 head)拿到锁后,调用了 await 方法,第一步创建一个 Node 节点,放到 Condition 自己的队列尾部,并唤醒 AQS 队列中的某个(head)节点,然后阻塞自己,等待被 signal 唤醒。当有其他线程调用了 signal 方法,就会唤醒 Condition 队列中的 first 节点,然后将这个节点放进 AQS 队列的尾部。阻塞在 await 方法的线程苏醒后,他已经从 Condition 队列总转移到 AQS 队列中了,这个时候,他就是一个正常的 AQS 节点,就会尝试抢锁。并清除 Condition 队列中无效的节点。

下面这张图说明了这几个步骤:

https://img1.sycdn.imooc.com//szimg/5c6393ab00016eae12921500.jpg

总的来说,就是在 Condition 中新增一个休眠队列来实现的。只要调用 await 方法,就会休眠,进入 Condition 队列,调用 signal 方法,就会从 Condition 队列中取出一个线程并插入到 AQS 队列中,然后唤醒,让这个线程自己去抢锁

0 回复 有任何疑惑可以回复我~
  • 提问者 红邮筒 #1
    那么老师,在Condition的等待队列中的Node的prev和next字段都是null,还是会按Condition的等待队列的顺序排列
    回复 有任何疑惑可以回复我~ 2019-02-13 19:45:39
  • Jimin 回复 提问者 红邮筒 #2
    其实点开Condition本身也是个interface,他的实现类是没有prev和next字段的,取而代之的是:Node firstWaiter 和 Node lastWaiter,就像第一幅图里画的那种,他本身属于对aqs组件的增强,而不是对aqs组件的实现。
    回复 有任何疑惑可以回复我~ 2019-02-13 22:42:05
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信