As a tool for concurrently sharing data and ensuring consistency, locks have multiple implementations on the JAVA platform (such as synchronized and ReentrantLock, etc.). These already written locks provide convenience for our development, but the specific nature and type of the locks are rarely mentioned. This series of articles will analyze common lock names and characteristics under JAVA to answer your questions.
blocking lock
Blocking locks, unlike spin locks, change the running state of the thread.
In the JAVA environment, thread Thread has the following states:
1. New state
2. Ready state
3. Running status
4. Blocked state
5. Death state
The blocking lock can be said to allow the thread to enter the blocking state and wait. When the corresponding signal (wake-up, time) is obtained, the thread can enter the ready state. All threads in the ready state enter the running state through competition.
In JAVA, the methods that can enter/exit, block state or contain blocking locks include, synchronized keyword (weight lock among them), ReentrantLock, Object.wait()/notify(), LockSupport.park()/unpart()( juc often used)
The following is an example of a JAVA blocking lock:
package lock;import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;import java.util.concurrent.locks.LockSupport;public class CLHLock1 { public static class CLHNode { private volatile Thread isLocked; } @SuppressWarnings("unused") private volatile CLHNode tail; private static final ThreadLocal<CLHNode> LOCAL = new ThreadLocal<CLHNode>(); private static final AtomicReferenceFieldUpdater<CLHLock1, CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock1.class, CLHNode.class, "tail"); public void lock() { CLHNode node = new CLHNode(); LOCAL .set(node); CLHNode preNode = UPDATER.getAndSet(this, node); if (preNode != null) { preNode.isLocked = Thread.currentThread(); LockSupport.park(this); preNode = null; LOCAL.set(node); } } public void unlock() { CLHNode node = LOCAL.get(); if (!UPDATER.compareAndSet(this, node, null)) { System.out.println("unlock/t" + node.isLocked.getName()); LockSupport.unpark(node.isLocked); } node = null; }}
Here we use the blocking lock of LockSupport.unpark(). This example is modified from the CLH lock.
The advantage of blocking locks is that blocked threads will not occupy CPU time and will not cause excessive CPU occupancy, but the entry time and recovery time are slightly slower than spin locks.
In the case of fierce competition, the performance of blocking locks is significantly higher than that of spin locks.
The ideal situation is; use spin locks when thread competition is not fierce, and use blocking locks when competition is fierce.
(Full text ends)