唤醒过程signal()
1.检查调用signal时,是否当前线程获取了锁,不是则抛异常
if (!isHeldExclusively()) throw new IllegalMonitorStateException();2.获取condition队列中的第一个等待节点
Node first = firstWaiter;if (first != null) doSignal(first);3.用CAS清除CONDITION状态
if (!node.compareAndSetWaitStatus(Node.CONDITION, 0)) return false;4.调用AQS的enq(firstWaitNode),将这个节点放入到同步队列的队尾(需要CAS支撑?因为可能是共享的,即使获取了锁也需要竞争)
Node p = enq(node);5.移动入同步队列成功后(可能经历了几次CAS),再用unpark方法唤醒,那个线程就进入了上面代码中Park之后的部分了
【详解AQS中的condition源码原理】int ws = p.waitStatus;if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL)) LockSupport.unpark(node.thread);6.如果是signalAll方法,则等待队列中每个节点都执行一次signal方法,全部移入同步队列中并唤醒(唤醒后他们很可能还会因为抢不到资源而阻塞,但队列位置不同了,也无法再通过sign唤醒了)
do { Node next = first.nextWaiter; first.nextWaiter = null; transferForSignal(first);first = next;} while (first != null);点击关注,第一时间了解华为云新鲜技术~
经验总结扩展阅读
- 朴东民是什么电影中的人物?
- 叶隐文正是什么电视剧中的人物?
- 最能洞察人心的星座隐藏在人群中的高手星座
- 哪些星座会因爱情失财
- 图数据 3D 可视化在 Explorer 中的应用
- .net 温故知新:【8】.NET 中的配置从xml转向json
- 2022兔年动土吉日查询
- 双燕和一凡是哪部电视剧中的人物?
- 厨师傻柱是什么电视剧中的人物?
- FHQ Treap 详解