J.U.C Aqs: Blocking and waking threads

Source: Internet
Author: User

All source code for this blog is from JDK 1.8

When the thread gets the synchronization state, if the acquisition fails, the CLH synchronization queue is added, and the synchronization state is continuously obtained by spinning, but in the process of spin, it is necessary to determine whether the current thread needs to block, and its main method is acquirequeued ():

If(shouldparkafterfailedacquire(p, node)&&  Parkandcheckinterrupt())=true;            

With this code we can see that after the failure to get the synchronization state, the thread does not immediately block, need to check the state of the thread, check the state of the method is Shouldparkafterfailedacquire (node pred, node node) method, This method mainly depends on the precursor node to determine whether the current thread should be blocked, the code is as follows:

    Private Static BooleanShouldparkafterfailedacquire(NodePred, NodeNode) { Precursor node IntWs=Pred.Waitstatus; The status is signal, which indicates that the current thread is in a wait state and is immediately put back to True If (Ws== Node.SIGNAL) Return True; The predecessor node State > 0, or cancelled, indicates that the node has timed out or been interrupted and needs to be canceled from the synchronization queue If (Ws> 0) { Do {Node.Prev=Pred=Pred.Prev; } While (Pred.Waitstatus> 0); Pred. = Node;} //precursor node state is condition, Propagate else { Compareandsetwaitstatus  (pred, Ws node. Signal } return ;                /span>                

This code primarily checks whether the current thread needs to be blocked, as follows:

    1. If the current thread's predecessor node state is sinnal, it indicates that the current thread needs to be blocked, call the Unpark () method to wake up, return true directly, and the current thread is blocked
    2. If the current thread's predecessor node status is cancelled (ws > 0), it indicates that the thread's precursor node has waited for a timeout or is interrupted, then the precursor node needs to be removed from the CLH queue until it goes back to the predecessor node State <= 0, returning false
    3. If the precursor node is non-sinnal, non-cancelled, the precursor node is set to Sinnal by CAs, which returns false

If the Shouldparkafterfailedacquire (node pred, node node) method returns True, the Parkandcheckinterrupt () method is called to block the current thread:

 private final  boolean Parkandcheckinterrupt ()  { locksupport. Parkthisreturn thread. Interrupted               /span>            

The Parkandcheckinterrupt () method mainly suspends the current thread, blocking the thread's call stack and returning the current thread's interrupt state. Inside it is the park () method that calls the Locksupport tool class to block the method.

After the thread releases the synchronization state, it needs to wake the thread's successor:

    Public Final BooleanRelease(IntArg) { If (Tryrelease(Arg)) { NodeH=Head; If  (h !=  Null && H.!= 0) //wakeup successor  Unparksuccessor (h return true;} return false }            /span>                

Call Unparksuccessor (node node) to wake the successor:

    Private voidUnparksuccessor(NodeNode) { Current node state IntWs=Node.Waitstatus; Current status < 0 is set to 0 If (Ws< 0)Compareandsetwaitstatus(Node,Ws, 0); Successor node of current node NodeS=Node.Next; The successor node is null or its status > 0 (timed out or interrupted) If (S== Null ||S.Waitstatus> 0) {S= Null; To find available nodes from the tail node For (NodeT=Tail;T!= Null &&T!=Node;T=T.Prev) If  (t. Waitstatus <= 0)  s Span class= "pun" >= T;} //wake-up successor  if   (s !=  Null  locksupport. (s. Thread }            /span>                

There may be a case where the successor of the current thread is null, timed out, interrupted, and if this is the case, you need to skip that node, but why start with the tail tail node instead of starting with Node.next? The reason is that node.next can still be null or canceled, so use the tail backtracking method to find the first available thread. Finally, call Locksupport's Unpark (thread thread) method to wake the thread.

Locksupport

From the above I can see that when it is necessary to block or wake up a thread, Aqs is done using the Locksupport tool class.

Locksupport is the basic thread blocking primitive used to create locks and other synchronization classes

Each thread that uses Locksupport is associated with a license, and if the license is available and can be used in the process, calling Park () will return immediately, otherwise it may be blocked. If the license is not yet available, you can call Unpark to make it available. However, note that the license is not reentrant, that is, the park () method can only be called once, otherwise it will be blocked.

Locksupport defines a series of methods that start with Park to block the current thread, Unpark the thread thread method to wake up a blocked thread. As follows:

The blocker parameter of the Park (object blocker) method is primarily used to identify the object that the current thread is waiting for, which is used primarily for troubleshooting and system monitoring.

The park method and the Unpark (thread thread) are paired, and Unpark must be executed after park executes, not to mention that the Unpark thread will always block without calling, and park has a method with a timestamp (Parknanos (Long Nanos): Disables the current thread for thread scheduling and waits up to the specified wait time, unless the license is available.

The source code for the park () method is as follows:

    Publicstaticvoid Park(){ UNSAFE.  Park(false,0L);}             

Unpark (thread thread) method source code is as follows:

public static void unpark(thread thread) { if  (thread  ! = null) UNSAFE.  Unpark(thread);  }< /c10>     

As can be seen from the above, the implementation of the internal is through the unsafe (sun.misc.Unsafe unsafe) to achieve, which is defined as follows:

public nativevoid Park (boolean var1 , long Var2 public native void< Span class= "PLN" > Unpark (object Var1  

All two are native local methods. Unsafe is a dangerous class that is primarily used to perform low-level, unsafe collection of methods. Although this class and all methods are public, the use of this class is still limited, and you cannot use the class directly in your own Java program, because only the code of the message can obtain an instance of the class.

Resources
    1. Fang Fei: "The Art of Java concurrent programming"
    2. Basic use of Locksupport Park and Unpark, and responsiveness to thread interrupts

J.U.C Aqs: Blocking and waking threads

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.