采纳答案成功!
向帮助你的同学说点啥吧!感谢那些助人为乐的人
1、Condition 对应的等待队列中的节点也是Node类的实例,且字段中的nextWaiter指向等待队列中的下一个节点,那么它字段中的prev,next指向什么?如果分别指向前一个节点和后一个节点,那么它怎么会是单向链表呢? 2、独占锁中使用Condition,当调用Condition.signal()时会唤醒Condition 对应的等待队列中的节点,加入到同步队列中,是先唤醒还是先把节点加入同步队列?此时同步队列中的节点是唤醒的还是阻塞的?
你好,先看一下Condition的关系图:
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 队列中无效的节点。
下面这张图说明了这几个步骤:
总的来说,就是在 Condition 中新增一个休眠队列来实现的。只要调用 await 方法,就会休眠,进入 Condition 队列,调用 signal 方法,就会从 Condition 队列中取出一个线程并插入到 AQS 队列中,然后唤醒,让这个线程自己去抢锁
那么老师,在Condition的等待队列中的Node的prev和next字段都是null,还是会按Condition的等待队列的顺序排列
其实点开Condition本身也是个interface,他的实现类是没有prev和next字段的,取而代之的是:Node firstWaiter 和 Node lastWaiter,就像第一幅图里画的那种,他本身属于对aqs组件的增强,而不是对aqs组件的实现。
登录后可查看更多问答,登录/注册
构建完整并发与高并发知识体系,倍增高薪面试成功率!
1.7k 1
1.1k 18
1.2k 15
3.6k 12
1.3k 12