閱讀185 返回首頁    go iPhone_iPad_Mac_apple


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

  上一篇:go  Java——ThreadLocal的使用
  下一篇:go  Hadoop 2.x 集群環境搭建