当前位置:网站首页>JUC concurrent programming 09 -- source code analysis of condition implementation
JUC concurrent programming 09 -- source code analysis of condition implementation
2022-04-23 10:04:00 【Half old 518】
have a look ReentrantLock Medium newCondition Method
final ConditionObject newCondition() {
return new ConditionObject();
}
Then click in and find that it is AQS Inner class in .
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
private transient Node firstWaiter;
private transient Node lastWaiter;
.....
}
Found no , There is also the definition of linked list operation , The principle of its implementation is conditional queue . Its structure can refer to the following figure .
We know , When a thread calls await When the method is used , Will enter the waiting state , Until used by other threads signal Method wake up . The waiting queue here is used to store the data in await The number of threads waiting .
Let's take a look at the most critical await How are methods implemented . Here, let's start with a few premises .
- Only threads that already hold locks can call this method .
- When this method is called , Will release the lock directly , No matter how many locks are added .
- Only other threads call
signalMethod or interrupt will wake up the waiting thread . - After being awakened, wait for other threads to release the lock , Only after you get the lock can you continue to execute , And it will return to its previous state (await After adding several layers of locks before, there are still several layers of locks ).
Take a look await The source code of the method .
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException(); // If you're calling await If it has been interrupted before , Throw an interrupt exception directly .
Node node = addConditionWaiter(); // Create a new node for the current thread , Add it to the condition queue
int savedState = fullyRelease(node); // Completely release the lock of the current thread , And save the status of the current thread , Because I have to recover
int interruptMode = 0; // Interrupt state
while (!isOnSyncQueue(node)) {
// Loop to determine whether it exists in AQS In the synchronization queue of ( If the waiting thread is awakened by another , Will enter AQS In the synchronization queue of , We will talk later )
LockSupport.park(this); // If it's still waiting , Suspend the thread
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) // Check if it was interrupted while waiting
break;
}
// Jumping out of the loop means that the thread must have been awakened , At this time, you only need to get the lock to run
if (acquireQueued(node, savedState) && interruptMode != THROW_IE) // Just try to get the lock , The process here is basically the same as that of a thread grabbing a lock
interruptMode = REINTERRUPT;
// After getting the lock, you can basically continue to run , Here are some basic cleaning work
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0) // It's still a response interrupt
reportInterruptAfterWait(interruptMode);
}
The above process is very regular , Nothing more than responding to interrupts 、 Thread hanging 、 Strong lock 、 Basic logic such as cleaning up , Look again. signal How is the method implemented . Before reading the source code , Let's clarify a few points first :
- Only the thread holding the lock can call
siganlMethod to wake up other threads . - First in the priority wake-up condition queue , If there is a problem during wake-up , Then look down , Until you find the first thread that can be awakened .
- In essence, the wake-up result is to throw the nodes of the conditional queue directly into the waiting queue , Let it compete for lock resources .
- After getting the lock , The thread can continue to execute .
The process can refer to the following figure .
Source code .
public final void signal() {
if (!isHeldExclusively()) // Check whether the current thread holds the lock
throw new IllegalMonitorStateException(); // You cannot wake up other threads without holding a lock
Node first = firstWaiter; // Get the first node of the condition queue
if (first != null) // The condition queue is not empty
doSignal(first); // Wake up the
}
doSignal
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null) // If the current node has no successor nodes , The condition queue is directly empty
lastWaiter = null; // This is equivalent to clearing the condition queue
first.nextWaiter = null; // Set the... Of the current node nextWaiter Set to empty , This is because the current node is out of the conditional queue
} while (!transferForSignal(first) && // Wake up the first node , There is no awakening ( Be cancelled ) And if the condition queue is not empty, it will cycle all the time
(first = firstWaiter) != null);
}
transferForSignal
final boolean transferForSignal(Node node) {
// If it's here CAS Failure , Probably because the thread was canceled
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// CAS success , Drop the node directly into AQS Waiting in the queue
Node p = enq(node); // enq Returns the predecessor node of the incoming node , I don't remember. I can look down
// End of core logic , The following code is a layer of optimization , You can jump out of the previous while loop
int ws = p.waitStatus; // Save the waiting state of the precursor node
// If the status of the precursor node is cancel , perhaps CAS Set it to signal Failure ( May be in ws>0 The moment after the cancellation )
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread); // Wake up the thread directly
return true;
}
I don't know how to join the team. Do you remember . I don't remember here. You can look at the code .
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) {
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
The figure below summarizes await,signal The fault of the .

版权声明
本文为[Half old 518]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230955171069.html
边栏推荐
- DBA常用SQL语句(1)— 概况信息
- Yarn核心参数配置
- SQL tuning series - SQL performance methodology
- 第一章 Oracle Database In-Memory 相关概念(续)(IM-1.2)
- 第二章 In-Memory 体系结构 (IM-2.2)
- NEC infrared remote control coding description
- Chapter 1 Oracle database in memory related concepts (im-1.1)
- Realize data value through streaming data integration (2)
- Custom login failure handling
- 工业元宇宙平台规划与建设
猜你喜欢
![[untitled]](/img/72/d3e46a820796a48b458cd2d0a18f8f.png)
[untitled]

Juc并发编程09——Condition实现源码分析

计算机网络安全实验二|DNS协议漏洞利用实验

正大国际讲解道琼斯工业指数到底是什么?

构建元宇宙时代敏捷制造的九种能力

Examination questions and answers of the third batch (main person in charge) of Guangdong safety officer a certificate in 2022

Operation of 2022 tea artist (primary) test question simulation test platform

Planning and construction of industrial meta universe platform

0704、ansible----01

Question bank and answers of Shanghai safety officer C certificate examination in 2022
随机推荐
art-template 模板引擎
Function realization of printing page
Realize data value through streaming data integration (2)
元宇宙时代的职业规划与执行
SQL调优系列文章之—SQL性能方法论
DBA常用SQL语句(2)— SGA和PGA
Pyqt5与通信
php 二维数组指定元素相等后相加否则新增
Failureforwardurl and failureurl
2022年流动式起重机司机考试题库模拟考试平台操作
[codeforces - 208e] blood cousins
[2020wc Day2] F. Clarice picking mushrooms (subtree and query, light and heavy son thought)
Chapter I Oracle database in memory related concepts (Continued) (im-1.2)
MapReduce核心和基础Demo
论文阅读《Integrity Monitoring Techniques for Vision Navigation Systems》——5结果
通过流式数据集成实现数据价值(3)- 实时持续数据收集
Cloud identity is too loose, opening the door for attackers
Sim Api User Guide(6)
Question bank and answers of Shanghai safety officer C certificate examination in 2022
第一章 Oracle Database In-Memory 相关概念(续)(IM-1.2)