您好,登錄后才能下訂單哦!
本篇內容介紹了“java的CLH隊列鎖是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
CLH隊列鎖是一種自旋鎖,提供先來先服務的公平性。
CLH基于鏈表實現。線程只是在不斷的自旋,不斷地輪詢前驅節點的狀態,如果前驅節點釋放了鎖,那么線程結束自旋。
對于持鎖時間很短的場景,比之間把線程阻塞住具有較高的性能,并能可以保持一定的公平性。
還有搭配自旋次數做深入的優化,使得使用場景更廣,性能更好。
對于特定應用場景,使用這種鎖可以提高性能,是一種鎖的優化方向。
核心理念就是,不要阻塞線程,用循環來替換。
一種LCH參考實現
public class ClhSpinLock implements Lock { /** * 前驅節點 每個線程 */ private final ThreadLocal<Node> prev = ThreadLocal.withInitial(Node::new); /** * 當前節點 */ private final ThreadLocal<Node> currentThreadNode = ThreadLocal.withInitial(Node::new); /** * 指向隊列末尾節點 * <p> * 值得注意 這個節點的默認值是false 也就是說 如果前驅節點是這個默認的節點 那么它是不會起到鎖的作用 * 即 第一個線程進來 執行lock()操作之后 立即返回 * <p> * 還有所有就是 所有的線程都共享這個tail引用 * 鏈表推進是依靠這個共享的tail */ private final AtomicReference<Node> tail = new AtomicReference<>(new Node()); public ClhSpinLock() { } /** * 1.初始狀態 tail指向一個node(head)節點 * +------+ * | head | <---- tail * +------+ * <p> * 2.lock-thread加入等待隊列: tail指向新的Node,同時Prev指向tail之前指向的節點 * +----------+ * | Thread-A | * | := Node | <---- tail * | := Prev | -----> +------+ * +----------+ | head | * +------+ * <p> * +----------+ +----------+ * | Thread-B | | Thread-A | * tail ----> | := Node | --> | := Node | * | := Prev | ----| | := Prev | -----> +------+ * +----------+ +----------+ | head | * +------+ * 3.尋找當前node的prev-node然后開始自旋 */ @Override public void lock() { // 值得注意的細節 // 如果是第一個線程進來 // 那么pred.locked是false 所以這個線程調用lock之后就直接返回了 // 第二個線程進來之后 它的pred就是第一個線程的 // 之后的線程以此類推 final Node currentThreadNode = this.currentThreadNode.get(); currentThreadNode.locked = true; // 所有線程都通過這個tail的不斷變換去推進 final Node prev = this.tail.getAndSet(currentThreadNode); // 這個只是滿足每個線程自己prev的設置 其實是可以省略掉的 this.prev.set(prev); // 自旋 while (prev.locked) { } } @Override public void unlock() { final Node node = this.currentThreadNode.get(); node.locked = false; this.currentThreadNode.set(this.prev.get()); } @Override public void lockInterruptibly() throws InterruptedException { } @Override public boolean tryLock() { return false; } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; } @Override public Condition newCondition() { return null; } private static class Node { private volatile boolean locked; } }
相關的測試代碼
public class ClhSpinLockTest { private static int count = 0; private static void testLock(Lock lock) { try { lock.lock(); System.out.println("任務啟動線程名稱:" + Thread.currentThread().getName() + " 任務開始時統計數:" + count + " 任務執行時間:" + System.currentTimeMillis()); for (int i = 0; i < 100; i++) { count++; } System.out.println("任務啟動線程名稱:" + Thread.currentThread().getName() + " 任務結束時統計數:" + count); } finally { lock.unlock(); } } public static void main(String[] args) { int workerThreadNums = 5; // 這個鎖是需要每個相關線程都需要持有的 final ClhSpinLock clhSpinLock = new ClhSpinLock(); // 這個是一個柵欄 目的是等到所有線程都執行完 看結果 final CyclicBarrier cyclicBarrier = new CyclicBarrier(workerThreadNums, () -> System.out.println("最終結果:" + count)); for (int i = 0; i < workerThreadNums; i++) { new Thread(() -> { testLock(clhSpinLock); try { cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } }).start(); } } }
空間復雜度低
在不同CPU結構體系下,性能是不同的。
“java的CLH隊列鎖是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。