LockSupport is a basic thread blocking primitive used to create locks and other synchronization classes.
The functions of park() and unpark() in LockSupport are to block threads and unblock threads, respectively, and park() and unpark() will not encounter the "deadlocks that may be caused by Thread.suspend and Thread.resume" problem.
Because park() and unpark() have permissions; competition between the thread calling park() and another thread trying to unpark() will remain active.
Basic usage
LockSupport is very similar to a binary semaphore (only 1 license is available). If this license has not been occupied, the current thread obtains the license and continues to execute; if the license has been occupied, the current thread blocks, waiting to obtain the license.
public static void main(String[] args){ LockSupport.park(); System.out.println("block.");}Running the code will reveal that the main thread is always blocking. Because the license is occupied by default, the license cannot be obtained when calling park(), so it enters a blocking state.
The following code: first release the license, then obtain the license, and the main thread can terminate normally. The acquisition and release of LockSupport licenses are generally corresponding. If you unpark multiple times, there will be no problem if you only park once. As a result, the license is in an available state.
public static void main(String[] args){ Thread thread = Thread.currentThread(); LockSupport.unpark(thread);//Release the license LockSupport.park();// Obtain the license System.out.println("b");}LockSupport is not reentrant. If a thread calls LockSupport .park() twice in a row, then the thread will definitely block.
public static void main(String[] args) throws Exception{ Thread thread = Thread.currentThread(); LockSupport.unpark(thread); System.out.println("a"); LockSupport.park(); System.out.println("b"); LockSupport.park(); System.out.println("c");}This code prints a and b, but does not print c, because the thread cannot obtain permission when calling park the second time.
Let's take a look at the response of LockSupport's corresponding interrupts
public static void t2() throws Exception{ Thread t = new Thread(new Runnable() { private int count = 0; @Override public void run() { long start = System.currentTimeMillis(); long end = 0; while ((end - start) <= 1000) { count++; end = System.currentTimeMillis(); } System.out.println("after 1 second.count=" + count); //Wait for permission to be allowed LockSupport.park(); System.out.println("thread over." + Thread.currentThread().isInterrupted()); } }); t.start(); Thread.sleep(2000); // interrupt thread t.interrupt(); System.out.println("main over");}The thread will print out thread over.true in the end. This means that if the thread blocks due to calling park, it can respond to an interrupt request (the interrupt status is set to true), but will not throw an InterruptedException.
LockSupport function list
// Returns the blocker object provided to the most recent unblocked park method call, and returns null if the call is not blocked. static Object getBlocker(Thread t)// For thread scheduling, disable the current thread unless the license is available. static void park()// For thread scheduling, disable the current thread before the license is available. static void park(Object blocker)// For thread scheduling, wait for the specified waiting time at most unless the license is available. static void parkNanos(long nanos)// For thread scheduling, disable the current thread before the license is available and wait for the specified waiting time at most. static void parkNanos(Object blocker, long nanos)// For thread scheduling, the current thread is disabled before the specified time limit unless the license is available. static void parkUntil(long deadline)// For thread scheduling, the current thread is disabled before the specified time limit unless the license is available. static void parkUntil(Object blocker, long deadline)// Make it available if the license of a given thread is not available yet. static void unpark(Thread thread)
LockSupport Example
Comparing "Example 1" and "Example 2" below can give you a clearer understanding of the usage of LockSupport.
Example 1
public class WaitTest1 { public static void main(String[] args) { ThreadA ta = new ThreadA("ta"); synchronized(ta) { // Get the "synchronization lock of object ta" through synchronized(ta) try { System.out.println(Thread.currentThread().getName()+" start ta"); ta.start(); System.out.println(Thread.currentThread().getName()+" block"); // The main thread is waiting for ta.wait(); System.out.println(Thread.currentThread().getName()+" continue"); } catch (InterruptedException e) { e.printStackTrace(); } } } static class ThreadA extends Thread{ public ThreadA(String name) { super(name); } public void run() { synchronized (this) { // Get "the synchronization lock of the current object" through synchronized(this) System.out.println(Thread.currentThread().getName()+" wakup others"); notify(); // Wake up "waiting thread on the current object" } } }} Example 2
import java.util.concurrent.locks.LockSupport;public class LockSupportTest1 { private static Thread mainThread; public static void main(String[] args) { ThreadA ta = new ThreadA("ta"); // Get the main thread mainThread = Thread.currentThread(); System.out.println(Thread.currentThread().getName()+" start ta"); ta.start(); System.out.println(Thread.currentThread().getName()+" block"); // The main thread blocks LockSupport.park(mainThread); System.out.println(Thread.currentThread().getName()+" continue"); } static class ThreadA extends Thread{ public ThreadA(String name) { super(name); } public void run() { System.out.println(Thread.currentThread().getName()+" wakup others"); // Wake up the "main thread" LockSupport.unpark(mainThread); } }} Running results:
main start tamain blockta wakup othersmain continue
Description: The difference between park and wait. Before waiting blocks threads, the synchronization lock must be obtained through synchronized.