這篇博客主要是做爲 AbstractQueuedSynchronizer 的背景知識介紹;平時接觸也很是的少,若是你不感興趣能夠跳過;可是瞭解一下能更加的清楚 AQS 的設計思路;java
一般狀況下解決多線程共享資源邏輯一致性問題有兩種方式:node
對於這兩種方式沒有優劣之分,只有是否適合當前的場景;具體的對比就不在繼續深刻了,若是你很感興趣能夠查看 《多處理器編程的藝術》 提取碼:rznn ;web
可是若是競爭很是激烈的時候,使用自旋鎖就會產生一些額外的問題:編程
解決這些問題其中的一種辦法就是使用隊列鎖,簡單來說就是讓這些線程排隊獲取;下面咱們介紹經常使用的兩種,即 CLH 鎖 和 MCS 鎖;多線程
CLH 是 Craig、Landin 和 Hagersten 三位做者的縮寫,具體內容在 《Building FIFO and Priority-Queuing Spin Locks from Atomic Swap》 論文中有詳細介紹,你們能夠自行查看;咱們 JDK 中 java.util.concurrent.locks.AbstractQueuedSynchronizer
就是根據 CLH 鎖的變種實現的;架構
簡單實現:ide
public class CLH implements Lock { private final ThreadLocal<Node> preNode = ThreadLocal.withInitial(() -> null); private final ThreadLocal<Node> node = ThreadLocal.withInitial(Node::new); private final AtomicReference<Node> tail = new AtomicReference<>(new Node()); private static class Node { private volatile boolean locked; } @Override public void lock() { final Node node = this.node.get(); node.locked = true; Node pre = this.tail.getAndSet(node); this.preNode.set(pre); while (pre.locked) ; } @Override public void unlock() { final Node node = this.node.get(); node.locked = false; this.node.set(this.preNode.get()); } }
一樣 MCS 是 John M. Mellor-Crummey 和 Michael L. Scott 名字的縮寫,具體內容能夠在 《Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors》 論文中查看;測試
簡單實現:ui
public class MCS implements Lock { private final ThreadLocal<Node> node = ThreadLocal.withInitial(Node::new); private final AtomicReference<Node> tail = new AtomicReference<>(); private static class Node { private volatile boolean locked = false; private volatile Node next = null; } @Override public void lock() { Node node = this.node.get(); node.locked = true; Node pre = tail.getAndSet(node); if (pre != null) { pre.next = node; while (node.locked) ; } } @Override public void unlock() { Node node = this.node.get(); if (node.next == null) { if (tail.compareAndSet(node, null)) { return; } while (node.next == null) ; } node.next.locked = false; node.next = null; } }