当前位置:网站首页>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
边栏推荐
- Redis database deployment and common commands
- Global and Chinese market of high-end home theater 2022-2028: Research Report on technology, participants, trends, market size and share
- Is there any good website or software for learning programming? [introduction to programming]?
- [RootersCTF2019]babyWeb
- [data recovery in North Asia] a data recovery case of raid crash caused by hard disk drop during data synchronization of hot spare disk of RAID5 disk array
- 提高企业产品交付效率系列(1)—— 企业应用一键安装和升级
- Go learning notes (5) basic types and declarations (4)
- Leetcode316- remove duplicate letters - stack - greedy - string
- Global and Chinese markets of InGaAs APD arrays 2022-2028: Research Report on technology, participants, trends, market size and share
- How to traverse massive data in redis
猜你喜欢

小程序常用组件小结

How to traverse massive data in redis

How to meet the requirements of source code confidentiality and source code security management

Distributed - summary list

Detailed explanation of set
![[data recovery in North Asia] a data recovery case of raid crash caused by hard disk drop during data synchronization of hot spare disk of RAID5 disk array](/img/22/606ff1e8dad3d5896b32d2146b0477.jpg)
[data recovery in North Asia] a data recovery case of raid crash caused by hard disk drop during data synchronization of hot spare disk of RAID5 disk array

C WPF uses dockpanel to realize screenshot box

CockroachDB: The Resilient Geo-Distributed SQL Database 论文阅读笔记

Set集合详细讲解

LRU cache for leveldb source code analysis
随机推荐
Global and Chinese market of search engine optimization (SEO) software 2022-2028: Research Report on technology, participants, trends, market size and share
Leetcode522- longest special sequence ii- hash table - String - double pointer
Distributed architecture system splitting principles, requirements and microservice splitting steps
AcWing 886. Finding combinatorial number II (pretreatment factorial)
Go learning notes (5) basic types and declarations (4)
Distributed transactions - Solutions
How to create a progress bar that changes color according to progress
Use of STM32 expansion board temperature sensor and temperature humidity sensor
Manually implement a simple stack
Unity project experience summary
了解 JVM 中几个相关问题 — JVM 内存布局、类加载机制、垃圾回收
Rust基础入门之变量绑定与解构
Implementation of distributed lock
Several methods of creating thread classes
Global and Chinese market of paper machine systems 2022-2028: Research Report on technology, participants, trends, market size and share
Flutter can refresh data every time the interface comes in
Fluentd is easy to use. Combined with the rainbow plug-in market, log collection is faster
复制宝贝提示材质不能为空,如何解决?
Ebpf cilium practice (2) - underlying network observability
el-cascader回显失败;el-cascader回显不出来