当前位置:网站首页>In depth understanding of condition source code interpretation and analysis of concurrent programming
In depth understanding of condition source code interpretation and analysis of concurrent programming
2022-07-01 05:25:00 【Jackli1123 (cross correlation second return)】
Deep understanding of concurrent programming Condition Source code analysis
List of articles
One 、Condition What is it?
Condition It's an interface , It provides two core methods ,await() and signal() Method , amount to Object Of wait and notify Method , perform await() Method to enter the waiting state of the thread will be placed in Condition In the single queue of . Note that both the wait and wake methods need to be executed between the code blocks of the lock .
- firstWaiter:Condition The first person in the queue
- lastWaiter:Condition The last person in the queue
- await(): The current thread is waiting
- signal(): Wake up a waiting thread
- signalAll(): Wake up all waiting threads
Two 、Condition Detailed analysis
1. Illustrate with examples Condition Usage of
public class Test {
private static Lock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " Thread gets lock ");
condition.await();
System.out.println(Thread.currentThread().getName() + " End of thread execution ");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
try {
Thread.sleep(3000);
} catch (Exception e) {
}
lock.lock();
condition.signal(); // Wakes up the waiting thread , Wakes up but does not execute , Because the lock tag is now held by the main thread
System.out.println(Thread.currentThread().getName() + " End of main thread execution ");
lock.unlock(); //lock The lock needs to be released , Threads 0 Only when the lock tag is obtained can it be executed
}
}
Take a look at the execution results , At the beginning, the thread executes printing and obtains the lock , Yes await() Method entry wait , sleep 3 Seconds passed , The main thread acquires the lock ( Because the lock mark will be released after entering the blocking state ), When the main thread is finished , Release the lock and the sub thread continues to execute from the waiting place , It should be noted here that the main thread will always be locked if it does not release the lock mark Blocked state , Because the lock mark is not found at all :
1.Condition Source code analysis
await()
Have a look first condition Waiting method source code
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter(); //Condition Add a waiting person to the waiting queue
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
// If the current thread's waitStatus Status as -2 Wait state , Then execute the loop . The state of the node creating the waiting queue must be -2
LockSupport.park(this); // Blocking the current thread
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) // The corresponding interrupt jumps out of the loop
break;
}
//acquireQueued in front Lock Also talked about , Is to perform lock() Method , Inside first CAS Try to acquire the lock. If the lock cannot be acquired, it will enter the blocking state . When multiple threads wake up at the same time, they will enter lock Blocked state , Here's the original state The status has been modified
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // There is no next waiting person to clear
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
/** 1. Add the method of waiting */
private Node addConditionWaiter() {
Node t = lastWaiter; // First time in t It's empty
if (t != null && t.waitStatus != Node.CONDITION) {
// If the last node is not empty and the state is not waiting, clean up the threads in the blocking queue that are not waiting
unlinkCancelledWaiters();
t = lastWaiter;
}
// Create a node of the current thread and hang it at the back of the waiting queue
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node; // You can see from here that , Only next But not pred explain Condition The queue of is one-way
lastWaiter = node;
return node; // Returns the node of the current thread
}
/** 2. Try to release the lock mark of the current thread and return to the original state , because lock The lock is reentrant , therefore state The value of is uncertain */
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState(); // Get the original state state
if (release(savedState)) {
// The current thread is unlocked , This is in Lock Of unlock() The method has already been discussed
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
/** 3. Will wait for the current wait -2 The status node is modified to 0 Waiting for lock status */
final boolean transferAfterCancelledWait(Node node) {
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
// At this time, the modification status is changed by -2 Turned into 0, Waiting becomes blocked
enq(node); // Here, the current node is added to the blocking queue
return true;
}
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
Sum up await() Steps for :
- stay Condition Add the current thread as one of the waiters
- Try to make the current thread release the lock mark and record the current thread's state
- Change the status of the current thread node to -2 Wait state , Then block the current thread until the interrupt response obtains the lock mark and is awakened
- The interrupt response jumps out of the loop , Will thread the state state ( Number of re-entry locks ) Change to the original state .
signal()
Have a look first condition Wake up method source code :
/** 1. Wake up the first one waiting */
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
/** 2. Wake up the first one waiting */
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null) // It is judged here that if the first node is the next node of the first , Then there is a waiting , Empty
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
/** 3. Set the current thread to 0 Blocked state , And join the last node in the blocking queue */
final boolean transferForSignal(Node node) {
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) // Change the status from -2 Turn into 0, Waiting becomes blocked
return false;
Node p = enq(node); // Set the current node as the last node in the blocking queue
int ws = p.waitStatus;
// If the node state >0, Just see if the lock tag is held by the current thread , Is to discard the lock tag , Generally, it will not wait for the thread to hold the lock mark
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
The method of awakening is relatively simple , Briefly describe what you did
- Change the state of the first node from -2 The waiting status is changed to 0 Blocked state
- Add this node to the blocking queue , Just wait to get the lock mark
Let's take a look at the following diagram to assume T1,T2,T3 How the three threads execute , hypothesis t2 Wait first , then t3 The wait method is executed again , Yes in the waiting pool t2 and t3, At this point, it wakes up t2, be t2 Entered the blocking queue , It is not directly implemented , Because I just wake up and haven't got the lock mark yet .
Content sources : Ant class
边栏推荐
- 云原生存储解决方案Rook-Ceph与Rainbond结合的实践
- Txncoordsender of cockroachdb distributed transaction source code analysis
- 实战:redux的基本使用
- Set集合详细讲解
- Global and Chinese market of solder wire 2022-2028: Research Report on technology, participants, trends, market size and share
- 如何创建一个根据进度改变颜色的进度条
- Rust hello-word
- 複制寶貝提示材質不能為空,如何解决?
- Use of STM32 expansion board temperature sensor and temperature humidity sensor
- CockroachDB 分布式事务源码分析之 TxnCoordSender
猜你喜欢

Set集合詳細講解

Explanation of characteristics of hydraulic slip ring

How to hide browser network IP address and modify IP internet access?

El cascade echo failed; El cascader does not echo

eBPF Cilium实战(2) - 底层网络可观测性

Leetcode1497- check whether array pairs can be divided by K - array - hash table - count

Numeric amount plus comma; JS two methods of adding three digits and a comma to numbers; JS data formatting

Unity drags and modifies scene camera parameters under the editor

Using nocalhost to develop microservice application on rainbow

Application and principle of ThreadPoolExecutor thread pool
随机推荐
Thread process foundation of JUC
What can the points mall Games bring to businesses? How to build a points mall?
QDataStream的簡單讀寫驗證
Like cloud functions
Youqitong [vip] v3.7.2022.0106 official January 22 Edition
Data consistency between redis and database
Thread safety issues
Understand several related problems in JVM - JVM memory layout, class loading mechanism, garbage collection
Rust hello-word
AcWing 884. Gauss elimination for solving XOR linear equations
Global and Chinese market of paper machine systems 2022-2028: Research Report on technology, participants, trends, market size and share
Global and Chinese market of mainboard 2022-2028: Research Report on technology, participants, trends, market size and share
el-form表单新增表单项动态校验;el-form校验动态表单v-if不生效;
如何选择导电滑环材料
Variable binding and deconstruction for rudimentary rust
导电滑环短路的原因以及应对措施
Distributed transactions - Solutions
复制宝贝提示材质不能为空,如何解决?
Application of industrial conductive slip ring
积分商城游戏能够给商家带来什么?怎么搭建积分商城?