当前位置:网站首页>AQS唤醒线程的时候为什么从后向前遍历,我懂了
AQS唤醒线程的时候为什么从后向前遍历,我懂了
2022-07-26 04:57:00 【知识浅谈】
先来熟悉一下代码,挂起和唤醒这两部分
尾部遍历源码
private void unparkSuccessor(Node node) { //获取wait状态 int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0);// 将等待状态waitStatus设置为初始值0 /** * 若后继结点为空,或状态为CANCEL(已失效),则从后尾部往前遍历找到最前的一个处于正常阻塞状态的结点 * 进行唤醒 */ Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread);//唤醒线程 }注意for循环中的逻辑:从尾部开始向前遍历,找到最前的一个处于正常阻塞状态的结点,直到节点重合(即等于当前节点)
高并发下入队逻辑
既然采用了从尾部遍历的逻辑,那么肯定是为了解决可能会出现的问题。而这个问题就在enq(…)方法中private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize //队列为空需要初始化,创建空的头节点 if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; //set尾部节点 if (compareAndSetTail(t, node)) { //当前节点置为尾部 t.next = node; //前驱节点的next指针指向当前节点 return t; } } } }原子性问题
在该段方法中,将当前节点置于尾部使用了CAS来保证线程安全,但是请注意:在if语句块中的代码并没有使用任何手段来保证线程安全!也就是说,在高并发情况下,可能会出现这种情况:
线程A通过CAS进入if语句块之后,发生上下文切换,此时线程B同样执行了该方法,并且执行完毕。然后线程C调用了unparkSuccessor方法。
假如是从头到尾的遍历形式,线程A的next指针此时还是null!也就是说,会出现后续节点被漏掉的情况。
图解流程
线程A执行CAS将当前节点置为尾部:
原本线程A要执行t.next = node;将node2的next设置为node3,但是,此时发生上下文切换,时间片交由线程B,也就是说,此时node2的next还是null
线程B执行enq逻辑,最终CLH队列如图所示:

此时发生上下文切换,时间片交由线程C,线程C调用了unparkSuccessor方法,假如是从头到尾的遍历形式,在node2就会发现,next指针为null,似乎没有后续节点了。
此时发生上下文切换,时间片交由线程A,A将node2的next=node3。奇怪的现象发生了:对于线程C来说,后续没有node3和node4,但是对于其它线程来说,却出现了这两个节点
结尾
从头部遍历会出现这种问题的原因我们找到了,最后我们再来说说为什么从尾部遍历不会出现这种问题呢?其最根本的原因在于:
node.prev = t;先于CAS执行,也就是说,你在将当前节点置为尾部之前就已经把前驱节点赋值了,自然不会出现prev=null的情况
边栏推荐
- 分子骨架跃迁工具-DeLinker介绍
- 3、 @requestmapping annotation
- Batch convert ppm format pictures to JPG format
- To study the trend of open source and gain insight into the future of the industry, stonedb community and the China Academy of communications and communications released the Research Report on the dev
- 批量将PPM格式图片转化为JPG格式
- Vector explanation and iterator failure
- UE4 keyboard control switch light
- 9 best project set management tools
- Niuke-top101-bm32
- What are the characteristics of the grammar of Russian documents in the translation of scientific papers
猜你喜欢

Ffmpeg video coding

SQL加解密注入详解

Switch to router technology: OSPF single zone configuration, OSPF multi zone and end zone

C language -- string function, memory function collection and Simulation Implementation

【语义分割】2018-DeeplabV3+ ECCV

这种是我的vs没连上数据库吗

can 串口 can 232 can 485 串口转CANbus总线网关模块CAN232/485MB转换器CANCOM

Kubernetes advanced training camp scheduler

时代潮流-云原生数据库的崛起

Customer service relationship management based on SQL net enterprise messenger enterprise communications
随机推荐
计算离散点的曲率(matlab)
What are the well-known to-do apps at home and abroad
What are the restrictions on opening futures accounts? Where is the safest place to open an account?
Recognized again | saining network security has been listed in the ccsip 2022 panorama of China's network security industry
Ffmpeg video coding
Use field parameters for report translation
NFT的几种发行方式你都了解过吗?不同的发行方式有什么优缺点?
十、拦截器
2022杭电多校第二场 A.Static Query on Tree(树剖)
Correspondence between IEC61131 data type and C data type
C language -- string function, memory function collection and Simulation Implementation
[cloud native | 17] four network modes of container
How to connect tdengine through idea database management tool?
Briefly describe the application fields of WMS warehouse management system
2022 Hangdian multi school DOS card (line segment tree)
Weights & biases (II)
ES6 modularization +commonjs
2022河南萌新联赛第(三)场:河南大学 A - 玉米大炮
汉字风格迁移篇---通过生成对抗网络学习一对多程式化汉字的转换和生成
2022 Henan Mengxin League game (3): Henan University a - corn cannon