CLH 鎖
概述
CLH鎖是一種自旋鎖,能確保無饑餓性,提供先來先服務的公平性。所謂的自旋是指:當線程試圖去拿已經被其它線程占有的鎖時,當前線程不會進入阻塞態,而是進入一個死循環去自旋的獲取鎖,獲取到鎖之後退出死循環。
同時CLH鎖也是一種基於鏈表的可擴展,高性能,公平的自旋鎖,申請線程隻在本地變量上自旋輪詢前驅的狀態,如果發現前驅釋放了鎖就結束自旋。
實驗
public class CLHLock implements Lock {
private final AtomicReference<QNode> tail;
private final ThreadLocal<QNode> myPred;
private final ThreadLocal<QNode> myNode;
public CLHLock() {
tail = new AtomicReference<QNode>(new QNode());
myNode = new ThreadLocal<QNode>() {
protected QNode initialValue() {
return new QNode();
}
};
myPred = new ThreadLocal<QNode>();
}
private static class QNode {
volatile boolean locked;
}
@Override
public void lock() {
QNode node = (QNode) myNode.get();
node.locked = true;
QNode pred = (QNode) tail.getAndSet(node);
myPred.set(pred);
while (pred.locked) {
}
}
@Override
public void unlock() {
QNode node = (QNode) myNode.get();
node.locked = false;
myNode.set(null);
myPred.set(null);
}
@Override
public void lockInterruptibly() throws InterruptedException {
// TODO Auto-generated method stub
}
@Override
public boolean tryLock() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
// TODO Auto-generated method stub
return false;
}
@Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}
}
public class CLHLockTest {
public static int tmp = 0;
public static CLHLock lock = new CLHLock();
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
new Thread(new Run()).start();
}
System.out.println(CLHLockTest.tmp);
}
}
class Run implements Runnable {
@Override
public void run() {
CLHLockTest.lock.lock();
CLHLockTest.tmp++;
CLHLockTest.lock.unlock();
}
}
CLHLock使用tail 這個變量來標記隊尾,當每個線程執行lock操作的時候,會生成相對應的myPred(指向前一個線程,以便監聽前一個線程的執行情況,如果前一個線程myNode.locked = true, 這個線程會一直執行死循環來自旋;如果前一個線程myNode.locked = false; 這個線程就可以獲取到鎖了),myNode(用來給它的後繼節點作為監聽對象)的線程局部變量。當一個線程獲取到鎖後進行解鎖時:它會獲取自身的myNode,將其中的locked 標誌位置為 false, 這樣它的後繼節點就可以從死循環中跳出來了(拿到鎖了)。
如有錯誤希望大家能指出來
參考資料:
https://www.cnblogs.com/yuyutianxia/p/4296220.html
https://googi.iteye.com/blog/1736570
最後更新:2017-07-13 09:02:20