当前位置:网站首页>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
边栏推荐
- 0xc000007b应用程序无法正常启动解决方案(亲测有效)
- Global and Chinese market of paper machine systems 2022-2028: Research Report on technology, participants, trends, market size and share
- Some common commands of podman
- Global and Chinese market of enterprise wireless LAN 2022-2028: Research Report on technology, participants, trends, market size and share
- tar命令
- Actual combat: gateway api-2022.2.13
- Usage and principle of synchronized
- Unity项目心得总结
- Summary of spanner's paper
- AcWing 886. Finding combinatorial number II (pretreatment factorial)
猜你喜欢

Daily question -leetcode1175- permutation of prime numbers - Mathematics

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

How to select conductive slip ring material

智慧运维:基于 BIM 技术的可视化管理系统

0xc000007b应用程序无法正常启动解决方案(亲测有效)

Intelligent operation and maintenance: visual management system based on BIM Technology
![Solution: thread 1:[< *> setvalue:forundefined key]: this class is not key value coding compliant for the key*](/img/88/0b99d1db2cdc70ab72d2b3c623dfaa.jpg)
Solution: thread 1:[< *> setvalue:forundefined key]: this class is not key value coding compliant for the key*

How to create a progress bar that changes color according to progress

Unity项目心得总结

Actual combat: basic use of Redux
随机推荐
Copier le matériel de conseils de bébé ne peut pas être vide, comment résoudre?
Implementation of distributed lock
Series of improving enterprise product delivery efficiency (1) -- one click installation and upgrade of enterprise applications
Sqlplus connects using the instance name
Distributed architecture system splitting principles, requirements and microservice splitting steps
Global and Chinese market for kitchen range hoods 2022-2028: Research Report on technology, participants, trends, market size and share
Buffer stream and transform stream
Intelligent operation and maintenance: visual management system based on BIM Technology
Actual combat: gateway api-2022.2.13
Global and Chinese market of enterprise wireless LAN 2022-2028: Research Report on technology, participants, trends, market size and share
More than one file was found with OS independent path ‘lib/armeabi-v7a/libyuv. so‘.
Use and principle of reentrantlock
1076 Forwards on Weibo
Cockroachdb: the resistant geo distributed SQL database paper reading notes
Global and Chinese markets of superconductor 2022-2028: Research Report on technology, participants, trends, market size and share
Copy baby prompt: material cannot be empty. How to solve it?
Global and Chinese markets of Ethernet communication modules 2022-2028: Research Report on technology, participants, trends, market size and share
如何开始学剪辑?零基础详细解析
Rust基础入门之变量绑定与解构
El cascade echo failed; El cascader does not echo