LockSupport for AQS framework thread blocking tool class, aqslocksupport

Source: Internet
Author: User

LockSupport for AQS framework thread blocking tool class, aqslocksupport

Preface

It has always been hard to understand in JDK, and it is also a very elegant language. He worships Doug Li. The author did not dare to give a long story. He just wanted to introduce the package to you in Theory and Practice (CODE) step by step.

In fact, it is very difficult to do everything, but as long as you write it down, you will not look forward to it. Thank you for your encouragement and help. Thank you ~ Okay. Warm up firstLockSupportLet's get started ~

 

LockSupportSummary

  • Definition: LockSupport is a tool class for thread blocking. It can be used to block and release a thread anywhere in the thread.
  • Function: LockSupport is usually not used directly. It is more of a basic tool class for Lock implementation.
  • Implementation: The underlying LockSupport relies on the UnSafe implementation, that is, the park () and unpark () primitive methods, replacing the status through "License"
  • Use: The park method is used for the thread to wait for "permission", and the unpark method is used to provide "permission" for the thread"
  • Supplement 1: Due to the existence of "License", when a thread calls the park method and other threads call the unpark method, it will remain active.
  • Supplement 2: If I open a JVM article, I will re-parse the underlying implementation of park and unpark from the JVM source code perspective. In essence, I use mutex and condition to maintain a _ counter (park-> 0, unpark-> 1) variable, that is, "License" is a one-time
  • Supplement 3: This is a summary of the AQS framework (in stock ).

 

LockSupportData Structure

1. Class Definition

public class LockSupport 

 

2. Constructor

// Private constructor, which Cannot be instantiated-essentially a work class, can only call the static method private LockSupport () {}// Cannot be instantiated.

 

3. UnSafe

// Hotspot implementation via intrinsics APIprivate static final sun. misc. unsafe UNSAFE; // used to record who is blocking the thread. It is used for thread monitoring and analysis tools to locate the cause, it indicates the offset of parkBlocker in the memory // The reason why the offset is used is because the thread must be blocked when parkBlockerOffset is assigned a value, and the method of direct calling during blocking is invalid. Only the memory private static final long parkBlockerOffset can be used; private static final long SEED; private static final long PROBE; private static final long SECONDARY; static {try {UNSAFE = sun. misc. unsafe. getUnsafe (); Class <?> Tk = Thread. class; // get the memory offset of the specified variable parkBlockerOffset = UNSAFE. objectFieldOffset (tk. getDeclaredField ("parkBlocker"); SEED = UNSAFE. objectFieldOffset (tk. getDeclaredField ("threadLocalRandomSeed"); PROBE = UNSAFE. objectFieldOffset (tk. getDeclaredField ("threadLocalRandomProbe"); SECONDARY = UNSAFE. objectFieldOffset (tk. getDeclaredField ("threadLocalRandomSecondarySeed");} catch (Exception ex) {throw new Error (ex );}}

 

4. permit (license)

  • LockSupportAnd every thread that uses it is associated with a permit. In a sense, it can be consideredSemaphoreClass, but unlike Semaphores, there is only one permit and cannot be accumulated (that is, repeated transfer of unpark will not be accumulated, up to 1)
  • Permit is equivalent to a switch (only 0 and 1 values). The default value is 0. The execution process is as follows:
    • Call the unpark method, permit + 1, that is, permit = 1
    • Call the park method. permit is consumed-1, that is, permit = 0. At the same time, the park method understands the returned results.
    • When the park method is called again, the thread will be blocked (at this time, permit = 0, the thread is not allowed to be available until permit = 1 will be blocked)

 

LockSupportData Structure

1. setBlocker/getBlocker

1/** 2 * Returns the blocker object supplied to the most recent 3 * invocation of a park method that has not yet unblocked, or null 4 * if not blocked. the value returned is just a momentary 5 * snapshot -- the thread may have since unblocked or blocked on a 6 * different blocker object. 7 * return the blocker object provided to the last park method call that has not been blocked. If the call is not blocked, return null 8 * @ param t the thread 9 * @ return the blocker10 * @ throws NullPointerException if argument is null11 * @ since 1.612 */13 public static Object getBlocker (Thread t) {14 if (t = null) 15 throw new NullPointerException (); 16 return UNSAFE. getObjectVolatile (t, parkBlockerOffset ); 17} 18/** 19 * This object is recorded while the thread is blocked to permit monitoring and diagnostic 20 * tools to identify the reasons that threads are blocked.21 * This object is blocked in the thread recorded, to allow monitoring tools and diagnostic tools to determine the cause of Thread congestion 22 */23 private static void setBlocker (Thread t, Object arg) {24 // Even though volatile, hotspot doesn' t need a write barrier here.25 UNSAFE. putObject (t, parkBlockerOffset, arg); 26}
  • By threadDumpCheck the information of the blocked stack, but the information is similar.

 

· 2. park

  • Function: This method is used to wait for "License". The following two conditions may occur during the call:
    • When "License" is available, return immediately and consume this license (turning the license into unavailable)
    • When "License" is unavailable, the current Thread may be blocked java. lang. Thread. State: WAITING parking
  • Use: Because the park method may return "no reason" at any time, it is usually used in a loop (check the condition again before returning)
  • Applicable: The park method is an optimization of "busy wait" (busy waiting) (that is, it does not need to waste too much time on spin), but it must be paired with unpark for more efficient use.
  • Note:: The permission of the park method is occupied by default. Calling the method before unpark will get the permission and be blocked.
Public static void park () {UNSAFE. park (false, 0L);} // The public static void parkNanos (long nanos) {if (nanos> 0) UNSAFE is returned when the time-out in the nanoseconds. park (false, nanos);} // wait in milliseconds // note that the system time and the time to wait must be used here // LockSupport. parkUntil (System. currentTimeMillis () + 3000); public static void parkUntil (long deadline) {UNSAFE. park (true, deadline);} // three forms of park also support one blocker object parameter. // It is recommended that you use these forms, instead of the original form without this parameter // The common parameter provided in the lock implementation as blocker is thispublic static void park (Object blocker) {Thread t = Thread. currentThread (); setBlocker (t, blocker); UNSAFE. park (false, 0L); setBlocker (t, null);} public static void parkNanos (Object blocker, long nanos) {if (nanos> 0) {Thread t = Thread. currentThread (); setBlocker (t, blocker); UNSAFE. park (false, nanos); setBlocker (t, null) ;}} public static void parkUntil (Object blocker, long deadline) {Thread t = Thread. currentThread (); setBlocker (t, blocker); UNSAFE. park (true, deadline); setBlocker (t, null );}

 

· 3. unpark

  • Function: This method is used to provide a "License" to make available the "License" that is still unavailable.
  • Note:: Because the park method is licensed by default to occupy and block threads, it is best to call unpark before calling park (of course, because the park \ unpark sequential decoupling, so the execution order does not matter, but it is best to follow the rule of releasing and getting again in the Code)
/*** Note: You must specify a Thread (but it doesn't matter whether the thread is park) and try to release the license */public static void unpark (Thread thread) {if (thread! = Null) UNSAFE. unpark (thread );}

 

· 4.LockSupportNon-reentrant

  • Non-reentrant: LockSupport cannot be reentrant. When a thread calls the park method multiple times, the thread will be blocked by the second park method.
1 public static void main (String [] args) {2 LockSupport. unpark (Thread. currentThread (); // we directly use the main thread 3 System. out. println ("Run unpark"); 4 LockSupport. park (); 5 System. out. println ("the first execution of the park"); 6 LockSupport. park (); 7 System. out. println ("Run the second park"); 8 while (true); 9} 10 --------------------- 11 // output: 12 run unpark13 run the first park14 // analysis: by printing the results, we can see that 7th rows are not actually printed. According to the following picture, we can see that the thread is blocked on 7th rows (corresponding to 16th rows of the image ).
  • UseJstackCommand to check the thread status, you will find that the thread isWAITINGStatus, that is, waiting for blocking, and still blocked by the park Method

 

· 5.LockSupportAnd interrupt

  • Interrupt response: LockSupport supports interrupt response. The thread can still respond to the interrupt request when calling park blocking, but does not throw an InterruptedException exception.
Public static void main (String [] args) {Thread thread = new Thread ()-> {long start = System. currentTimeMillis (); while (System. currentTimeMillis ()-start) <= 1000); // idling 1 s System. out. println ("idling to 1 s"); LockSupport. park (); // wait for "License" System. out. println (Thread. currentThread (). getName () + "interrupted:" + Thread. currentThread (). isInterrupted () ;}, "kira"); thread. start (); thread. interrupt (); // interrupt thread} ------------------- // output: Empty to 1 s to end whether kira is interrupted: true // analysis: the interrupt response can be obtained by interrupting the thread first and then park, no exception is thrown.

 

■ Suspend () VS wait () VS park ()

1. suspend () VS wait ()

  • Suspend () does not release the lock. wait () releases the lock and supports timeout processing.

2. suspend () VS wait ()

  • LockSupport solves the issue that suspend () does not release the lock and thus easily deadlocks. For example, when the resume () method is blocked, other threads call resume () the method is blocked when the Synchronous lock is obtained, and the resume () method cannot be executed, resulting in a deadlock.

3. park () VS wait ()

  • LockSupportThe InterruptedException exception does not need to be obtained first.
  • UnparkThe method can be called before the park method, and there is no time sequence problem of the method call.
  • Wait/notifyA problem with the mechanism is that when the thread calls the notify method to wake up other threads, it is necessary to ensure that the thread to be awakened must be blocked by the wait method; otherwise, the wake-up thread will always be inWAITINGThe notify method can only wake up one thread. When multiple threads are on the same object at the same timeWaitWait, only one thread can be awakened (not specified)
  • Park/unparkThe Mechanism decouples thread synchronization by introducing the concept of a single "License", so there is no need to care about the status of the other thread, because no variable is needed for storing the status

 

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.