java high concurrency series 9

Keywords: Hibernate Java

JAVA LockSupport Tool Class

LockSupport

LockSupport is the basic thread blocking primitive used to create locks and other synchronization classes.
The LockSupport class can block the current thread and wake up the specified blocked thread. The main methods are park() and unpark(thread) to block and wake up threads.
Each thread has a permit, which has only two values 1 and 0 by default.
When the unpark(thread) method is called, the thread's license permit is set to 1
When the park() method is called, if the permit of the current thread is 1, set permit to 0 and return immediately. If the permit of the current thread is 0, the current thread will block until other threads set the permit of the current thread to 1, the park method will be waked up, and then the permit will be set to 0 again and returned.

Common methods in LockSupport

Blocking method:

	//Blocking the current thread and returning from the park() method only if the unpark method is called or if the current thread is interrupted
    public static void park() {
        UNSAFE.park(false, 0L);
    }
    //Blocking the current thread and returning from the park() method only if the unpark method is called or if the current thread is interrupted
    //Include an Object object to record the blocked objects that cause thread blocking and facilitate problem checking
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }
    //Blocking the current thread up to nanos nanoseconds increases the timeout return feature
    public static void parkNanos(long nanos) {
        if (nanos > 0)
            UNSAFE.park(false, nanos);
    }
    //Blocking the current thread up to nanos nanoseconds increases the timeout return feature
    // Include an Object object to record the blocked objects that cause thread blocking and facilitate problem checking
    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);
        }
    }
    //Blocking the current thread until deadline, deadline is an absolute time, in millisecond format for a certain time
    public static void parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }
    //Block the current thread until deadline
    //Include an Object object to record the blocked objects that cause thread blocking and facilitate problem checking
    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }

Wake-up method:

//Wake up the specified thread in the blocked state
public static void unpark(Thread thread) {
	if (thread != null)
       UNSAFE.unpark(thread);
}

Example: The main thread thread wakes up thread 1 after waiting for 5 seconds

public class MyThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() ->{
            System.out.println(Thread.currentThread().getName() + " start!");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " To be awakened!");
        });
        t1.setName("Thread 1");
        t1.start();
        //Hibernate for 5 seconds
        TimeUnit.SECONDS.sleep(5);
        LockSupport.unpark(t1);
        System.out.println("LockSupport.unpark();completion of enforcement");
    }
}

Output results:

Thread 1 start!
LockSupport.unpark(); Executed
 Thread 1 is awakened!

analysis
Call LockSupport.park() in thread 1; let the current thread 1 wait, after the main thread sleeps for 5 seconds, call LockSupport.unpark(t1); wake up thread 1, the output results of one or three lines are about 5 seconds apart, indicating that thread 1 is awakened after waiting for 5 seconds.
LockSupport.park(); no parameters, internal will directly keep the current thread waiting; unpark method passes a thread object as a parameter, indicating that the corresponding thread will wake up.
Example code 2: Wake-up method is executed before wait method

public class MyThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() ->{
            //Hibernate for 5 seconds
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " start!");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " To be awakened!");
        });
        t1.setName("Thread 1");
        t1.start();
        //Hibernate for 5 seconds
        TimeUnit.SECONDS.sleep(1);
        LockSupport.unpark(t1);
        System.out.println("LockSupport.unpark();completion of enforcement");
    }
}

Output results:

LockSupport.unpark(); Executed
 Thread 1 start!
Thread 1 is awakened!

Analysis:
Start thread 1, thread 1 internal dormancy for 5 seconds, and then after the main thread dormancy for 1 second, call LockSupport.unpark(t1); wake up thread 1, at this time LockSupport.park(); method has not been executed. LockSupport.park(); no blocking, it returns immediately.
The wake-up method executes before it waits for the method, and the thread can also be waked up, which is not possible with the other two methods. Wake-up in Object and Condition must be called after waiting for the thread to be waked up. In LockSupport, the wake-up method can be called either before or after the wait, and the thread can be waked up.
After par () lets the thread wait

public class MyThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() ->{
            System.out.println(Thread.currentThread().getName() + " start!");
            System.out.println(Thread.currentThread().getName() + ",park()Previous interruption signs:" + Thread.currentThread().isInterrupted());
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + ",park()After that, the interruption sign:" + Thread.currentThread().isInterrupted());
            System.out.println(Thread.currentThread().getName() + " To be awakened!");
        });
        t1.setName("t1");
        t1.start();
        //Hibernate for 5 seconds
        TimeUnit.SECONDS.sleep(5);
        t1.interrupt();
    }
}

Output results:

t1 start!
t1,park()Previous interruption signs:false
t1,park()After that, the interruption sign:true
t1 To be awakened!

Analysis:
The park() method is called in T1 thread to make the thread wait. After the main thread has been dormant for 5 seconds, t1.interrupt() is called; the interrupt signal is sent to T1 thread, and then the thread T1 is awakened from the waiting. The result of the output is about 5 seconds apart from the result of 1 or 4 lines, which happens to wake T1 after the main thread has been dormant for 5 seconds. Conclusion: The park method can interrupt the corresponding threads.
Two ways to wake up a thread:

  1. Call the LockSupport.unpark method
  2. Call the interrupt() method of the waiting thread to send an interrupt signal to the waiting thread to wake up the thread
Contrast term Object Condtion LockSupport
Pre-conditions Need to run in synchronized Lock locks need to be acquired first nothing
Unlimited waiting Support Support Support
Overtime waiting Support Support Support
Waiting to return sometime in the future I won't support it Support Support
Release locks in wait state Will be released Will be released Not released
Whether a wake-up method can wake up a thread before a wait method can execute no no Sure
Can you respond to thread interrupts? yes yes yes
Does thread interrupt clear interrupt flags yes yes no
Do you support non-response interruption in wait state? I won't support it Support I won't support it

Posted by roneill on Mon, 09 Sep 2019 01:30:36 -0700