Look at Craig, Landin, and Hagersten invented the CLH lock how to optimize the cost of synchronization, the core idea is: through a certain means of all threads to a shared variable polling competition into a thread queue and threads in the queue each polling their own local variables. This conversion process consists of two key points, one is how to build the queue & how to build the queue, in order to ensure fairness, the building will be a FIFO queue, when the building is mainly through the mobile tail node tail to achieve queue queuing, Each thread that wants to acquire a lock creates a new node and assigns the new node to tail through CAS atomic operations, and then lets the current thread poll one of the previous node's state bits, 2-5-9-3, so that the thread queuing queue is successfully built, and the second is how to release the queue. After executing the thread, only the node state position corresponding to the current thread is unlocked, and the lock is acquired because the next node is polling.
Figure 2-5-9-3 CLH Lock
The core idea of the CLH lock seems to be that many threads are competing for a resource over a long period of time, and by ordering these threads into a single local variable detection. The only place where competition exists is the tail of the tail node before entering the queue, but the number of competing threads is much less, and there is a lot fewer polling times than all threads competing directly against a resource, which saves a lot of CPU cache synchronization operations, greatly improves system performance, and uses space in exchange for performance. The following provides a simple CLH lock implementation code, lock and Unlock two method provides lock unlock operation, each lock unlock must be a Clhnode object as a parameter, the lock method for loop is the CAS operation to the new node into the queue, The while loop detects the lock state bit of the precursor node and, once the predecessor node lock state bit is allowed, ends the detection and allows the thread to execute down. The unlock operation first determines whether the current node is the tail node, if the tail node is set to empty, at this point the name is only one thread executing, otherwise the current node's lock state position is unlocked.
public class Clhlock {
private static unsafe unsafe = null;
Private static final long valueoffset;
private volatile clhnode tail;
public class Clhnode {
Private Boolean isLocked = true;
}
static {
try {
unsafe = getunsafeinstance ();
Valueoffset = Unsafe.objectfieldoffset (clhlock.class
. Getdeclaredfield ("tail"));
} catch (Exception ex) {
throw new Error (ex);
}
}
public void Lock (Clhnode currentthreadnode) {
Clhnode prenode = null;
for (;;) {
Prenode = tail;
if (Unsafe.compareandswapobject (this, valueoffset, tail,
Currentthreadnode))
Break
}
if (Prenode! = null)
while (prenode.islocked) {
}
}
public void Unlock (Clhnode currentthreadnode) {
if (!unsafe.compareandswapobject (this, Valueoffset, Currentthreadnode,null))
currentthreadnode.islocked = false;
}
private static Unsafe Getunsafeinstance () throws SecurityException,
Nosuchfieldexception, IllegalArgumentException,
illegalaccessexception {
Field theunsafeinstance = Unsafe.class.getDeclaredField ("Theunsafe");
Theunsafeinstance.setaccessible (TRUE);
Return (Unsafe) theunsafeinstance.get (Unsafe.class);
}
}
Java concurrency framework--aqs blocking queue Management (ii)