synchronized和lock詳解
一、synchronized原理詳解
1. 設計同步器的意義
多執行緒可能會同時訪問一個共享、可變的資源,這個資源稱之為臨界資源,需要同步機制來協同物件可變狀態的訪問,同步器的本質就是加鎖,即同一時刻只能有同一個執行緒訪問臨界資源,也稱為同步互斥訪問
sychronized內建鎖是一種物件鎖(鎖的是物件,而非引用),可以實現臨界資源的互斥訪問,是可重入的
2. 加鎖的方式
- 同步例項方法,鎖是當前例項物件
- 同步類方法,鎖是當前類物件
- 同步程式碼塊,鎖是括號裡面的物件
3. synchronized原理詳解
JVM在1.5之後版本做了重大的優化,如鎖粗化,鎖消除,偏向鎖,輕量級鎖,鎖自旋等操作來減少鎖的開銷
① 偏向鎖 : 在大多數情況下,鎖不僅存在多執行緒競爭,而且總是由同一個執行緒多次獲得,故而引入偏向鎖,核心思想是 : 如果一個執行緒獲取了鎖,那麼進入偏向模式,此時Mark Word 的結構也就變成了偏向鎖結構,當執行緒再次請求鎖時,無需做任何同步操作,即可獲取鎖的過程,省去了大量的有關鎖申請的操作,從而提高了程式的效能
② 輕量級鎖 : 輕量級鎖所適應的場景是,執行緒交替執行同步程式碼塊的場合,如果存在同一時間內訪問同一鎖的場合,就會導致輕量級鎖膨脹為重量級鎖
③ 自旋鎖 : 應用場景是,大多數情況下,執行緒持有鎖的時間都不會太長,如果直接掛起作業系統層面的執行緒就會得不償失,畢竟執行緒之間的切換需要從使用者狀態轉換到核心態,這個狀態之間的轉換需要較長的時間,虛擬機器假設在不久的將來,當前執行緒可以獲得鎖,虛擬機器會讓當前獲取鎖的執行緒做幾個空迴圈,經過幾次空迴圈後,如果得到鎖,就順利進入臨界區,如果得不到鎖,就係統層面掛起
④ 鎖消除 : java虛擬機器在JIT編譯時,通過上下文的掃描,去除不存在共享資源競爭的鎖,通過這種方式消除沒有必要的鎖,可以節省毫無意義的請求鎖的時間
⑤ 重量級鎖 : synchronized是基於JVM內建鎖的實現,通過內部物件Monitor(監視器鎖)實現,基於進入與退出monitor物件實現方法與程式碼塊同步,監視器鎖的實現依賴底層作業系統Mutex lock的實現,他是一個重量級鎖,效能較低.
4.ReentrantLock
是一種基於AQS框架的實現,是JDK中的執行緒併發訪問的同步手段,他的功能類似於synchronized,是一種互斥鎖,可以保證執行緒安全.而且比synchronized具有更多的特性,比如它支援手動加鎖與解鎖,支援鎖的公平性.
除了Lock外, java.current.util當中同步器的實現如Latch, Barrier, BlockingQueue等,都是基於AQS框架實現.
一般是通過定義內部類Sync整合AQS, 將同步器所有都對映到Sync對應的方法
5. AQS
特性 : 阻塞等待佇列, 共享/獨佔 ,公平/非公平, 可重入, 允許中斷
內部維護屬性 : volatile int state ,state表示資源的可用狀態
State三種訪問方式 : getState(), setState(), compareAndSetState()
兩種資源的共享方式 :
Exclusive-獨佔 : 只有一個執行緒能執行, 如ReentrantLock
share-共享 : 多個執行緒可以同時執行, 如Semphore/CountdownLatch
定義兩種佇列:
同步等待佇列
條件等待佇列
自定義同步器主要實現以下幾種方法 :
isHeldExclusively() : 該執行緒是否正在獨佔資源. 只有用到condition才需要去實現它.
tryAcquire(int) : 獨佔方式. 嘗試獲取資源,成功返回true, 失敗返回false.
tryRelease(int) : 獨佔方式, 嘗試釋放資源,成功返回true,失敗返回false.
tryAcquireShared(int) : 共享方式. 嘗試獲取資源,負數表示失敗; 0表示成功,但沒有剩餘剩餘可用資源; 正數表示成功,且有剩餘資源.
tryReleaseShared(int) : 共享方式. 嘗試釋放資源, 如果釋放後允許喚醒後續等待節點返回true,否則返回false.
CLH同步等待佇列
CLH是一種FIFO先入先出執行緒等待佇列,Java中的CLH是原CLH的一個變種,執行緒由原自旋改為阻塞機制
Condition條件等待佇列
是一個多執行緒協調通訊的工具類,使得某個或者某些執行緒一起等待某個條件,只有當條件具備時,這些執行緒才會被喚醒,從而重新爭奪鎖
AQS原始碼分析
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { private static final long serialVersionUID = 7373984972572414691L; /** * Creates a new {@code AbstractQueuedSynchronizer} instance * with initial synchronization state of zero. */ protected AbstractQueuedSynchronizer() { } /** * Wait queue node class. * * 不管是條件佇列,還是CLH等待佇列 * 都是基於Node類 * * AQS當中的同步等待佇列也稱CLH佇列,CLH佇列是Craig、Landin、Hagersten三人 * 發明的一種基於雙向連結串列資料結構的佇列,是FIFO先入先出執行緒等待佇列,Java中的 * CLH佇列是原CLH佇列的一個變種,執行緒由原自旋機制改為阻塞機制。 */ static final class Node { /** * 標記節點未共享模式 * */ static final Node SHARED = new Node(); /** * 標記節點為獨佔模式 */ static final Node EXCLUSIVE = null; /** * 在同步佇列中等待的執行緒等待超時或者被中斷,需要從同步佇列中取消等待 * */ static final int CANCELLED = 1; /** * 後繼節點的執行緒處於等待狀態,而當前的節點如果釋放了同步狀態或者被取消, * 將會通知後繼節點,使後繼節點的執行緒得以執行。 */ static final int SIGNAL = -1; /** * 節點在等待佇列中,節點的執行緒等待在Condition上,當其他執行緒對Condition呼叫了signal()方法後, * 該節點會從等待佇列中轉移到同步佇列中,加入到同步狀態的獲取中 */ static final int CONDITION = -2; /** * 表示下一次共享式同步狀態獲取將會被無條件地傳播下去 */ static final int PROPAGATE = -3; /** * 標記當前節點的訊號量狀態 (1,0,-1,-2,-3)5種狀態 * 使用CAS更改狀態,volatile保證執行緒可見性,高併發場景下, * 即被一個執行緒修改後,狀態會立馬讓其他執行緒可見。 */ volatile int waitStatus; /** * 前驅節點,當前節點加入到同步佇列中被設定 */ volatile Node prev; /** * 後繼節點 */ volatile Node next; /** * 節點同步狀態的執行緒 */ volatile Thread thread; /** * 等待佇列中的後繼節點,如果當前節點是共享的,那麼這個欄位是一個SHARED常量, * 也就是說節點型別(獨佔和共享)和等待佇列中的後繼節點共用同一個欄位。 */ Node nextWaiter; /** * Returns true if node is waiting in shared mode. */ final boolean isShared() { return nextWaiter == SHARED; } /** * 返回前驅節點 */ final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } //空節點,用於標記共享模式 Node() { // Used to establish initial head or SHARED marker } //用於同步佇列CLH Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } //用於條件佇列 Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } } /** * 指向同步等待佇列的頭節點 */ private transient volatile Node head; /** * 指向同步等待佇列的尾節點 */ private transient volatile Node tail; /** * 同步資源狀態 */ private volatile int state; /** * * @return current state value */ protected final int getState() { return state; } protected final void setState(int newState) { state = newState; } /** * Atomically sets synchronization state to the given updated * value if the current state value equals the expected value. * This operation has memory semantics of a {@code volatile} read * and write. * * @param expect the expected value * @param update the new value * @return {@code true} if successful. False return indicates that the actual * value was not equal to the expected value. */ protected final boolean compareAndSetState(int expect, int update) { // See below for intrinsics setup to support this return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } // Queuing utilities /** * The number of nanoseconds for which it is faster to spin * rather than to use timed park. A rough estimate suffices * to improve responsiveness with very short timeouts. */ static final long spinForTimeoutThreshold = 1000L; /** * 節點加入CLH同步佇列 */ private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize //佇列為空需要初始化,建立空的頭節點 if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; //set尾部節點 if (compareAndSetTail(t, node)) {//當前節點置為尾部 t.next = node; //前驅節點的next指標指向當前節點 return t; } } } } /** * Creates and enqueues node for current thread and given mode. * * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared * @return the new node */ private Node addWaiter(Node mode) { // 1. 將當前執行緒構建成Node型別 Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; // 2. 1當前尾節點是否為null? if (pred != null) { // 2.2 將當前節點尾插入的方式 node.prev = pred; // 2.3 CAS將節點插入同步佇列的尾部 if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; } /** * Sets head of queue to be node, thus dequeuing. Called only by * acquire methods. Also nulls out unused fields for sake of GC * and to suppress unnecessary signals and traversals. * * @param node the node */ private void setHead(Node node) { head = node; node.thread = null; node.prev = null; } /** * */ private void unparkSuccessor(Node node) { //獲取wait狀態 int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0);// 將等待狀態waitStatus設定為初始值0 /** * 若後繼結點為空,或狀態為CANCEL(已失效),則從後尾部往前遍歷找到最前的一個處於正常阻塞狀態的結點 * 進行喚醒 */ Node s = node.next; //head.next = Node1 ,thread = T3 if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread);//喚醒執行緒,T3喚醒 } /** * 把當前結點設定為SIGNAL或者PROPAGATE * 喚醒head.next(B節點),B節點喚醒後可以競爭鎖,成功後head->B,然後又會喚醒B.next,一直重複直到共享節點都喚醒 * head節點狀態為SIGNAL,重置head.waitStatus->0,喚醒head節點執行緒,喚醒後執行緒去競爭共享鎖 * head節點狀態為0,將head.waitStatus->Node.PROPAGATE傳播狀態,表示需要將狀態向後繼節點傳播 */ private void doReleaseShared() { for (;;) { Node h = head; if (h != null && h != tail) { int ws = h.waitStatus; if (ws == Node.SIGNAL) {//head是SIGNAL狀態 /* head狀態是SIGNAL,重置head節點waitStatus為0,E這裡不直接設為Node.PROPAGAT, * 是因為unparkSuccessor(h)中,如果ws < 0會設定為0,所以ws先設定為0,再設定為PROPAGATE * 這裡需要控制併發,因為入口有setHeadAndPropagate跟release兩個,避免兩次unpark */ if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; //設定失敗,重新迴圈 /* head狀態為SIGNAL,且成功設定為0之後,喚醒head.next節點執行緒 * 此時head、head.next的執行緒都喚醒了,head.next會去競爭鎖,成功後head會指向獲取鎖的節點, * 也就是head發生了變化。看最底下一行程式碼可知,head發生變化後會重新迴圈,繼續喚醒head的下一個節點 */ unparkSuccessor(h); /* * 如果本身頭節點的waitStatus是出於重置狀態(waitStatus==0)的,將其設定為“傳播”狀態。 * 意味著需要將狀態向後一個節點傳播 */ } else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } if (h == head) //如果head變了,重新迴圈 break; } } /** * 把node節點設定成head節點,且Node.waitStatus->Node.PROPAGATE */ private void setHeadAndPropagate(Node node, int propagate) { Node h = head; //h用來儲存舊的head節點 setHead(node);//head引用指向node節點 /* 這裡意思有兩種情況是需要執行喚醒操作 * 1.propagate > 0 表示呼叫方指明瞭後繼節點需要被喚醒 * 2.頭節點後面的節點需要被喚醒(waitStatus<0),不論是老的頭結點還是新的頭結點 */ if (propagate > 0 || h == null || h.waitStatus < 0 || (h = head) == null || h.waitStatus < 0) { Node s = node.next; if (s == null || s.isShared())//node是最後一個節點或者 node的後繼節點是共享節點 /* 如果head節點狀態為SIGNAL,喚醒head節點執行緒,重置head.waitStatus->0 * head節點狀態為0(第一次新增時是0),設定head.waitStatus->Node.PROPAGATE表示狀態需要向後繼節點傳播 */ doReleaseShared(); } } // Utilities for various versions of acquire /** * 終結掉正在嘗試去獲取鎖的節點 * @param node the node */ private void cancelAcquire(Node node) { // Ignore if node doesn't exist if (node == null) return; node.thread = null; // 剔除掉一件被cancel掉的節點 Node pred = node.prev; while (pred.waitStatus > 0) node.prev = pred = pred.prev; // predNext is the apparent node to unsplice. CASes below will // fail if not, in which case, we lost race vs another cancel // or signal, so no further action is necessary. Node predNext = pred.next; // Can use unconditional write instead of CAS here. // After this atomic step, other Nodes can skip past us. // Before, we are free of interference from other threads. node.waitStatus = Node.CANCELLED; // If we are the tail, remove ourselves. if (node == tail && compareAndSetTail(node, pred)) { compareAndSetNext(pred, predNext, null); } else { // If successor needs signal, try to set pred's next-link // so it will get one. Otherwise wake it up to propagate. int ws; if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && pred.thread != null) { Node next = node.next; if (next != null && next.waitStatus <= 0) compareAndSetNext(pred, predNext, next); } else { unparkSuccessor(node); } node.next = node; // help GC } } /** * */ private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; if (ws == Node.SIGNAL) /* * 若前驅結點的狀態是SIGNAL,意味著當前結點可以被安全地park */ return true; if (ws > 0) { /* * 前驅節點狀態如果被取消狀態,將被移除出佇列 */ do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { /* * 當前驅節點waitStatus為 0 or PROPAGATE狀態時 * 將其設定為SIGNAL狀態,然後當前結點才可以可以被安全地park */ compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; } /** * 中斷當前執行緒 */ static void selfInterrupt() { Thread.currentThread().interrupt(); } /** * 阻塞當前節點,返回當前Thread的中斷狀態 * LockSupport.park 底層實現邏輯呼叫系統核心功能 pthread_mutex_lock 阻塞執行緒 */ private final boolean parkAndCheckInterrupt() { LockSupport.park(this);//阻塞 return Thread.interrupted(); } /** * 已經在隊列當中的Thread節點,準備阻塞等待獲取鎖 */ final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) {//死迴圈 final Node p = node.predecessor();//找到當前結點的前驅結點 if (p == head && tryAcquire(arg)) {//如果前驅結點是頭結點,才tryAcquire,其他結點是沒有機會tryAcquire的。 setHead(node);//獲取同步狀態成功,將當前結點設定為頭結點。 p.next = null; // help GC failed = false; return interrupted; } /** * 如果前驅節點不是Head,通過shouldParkAfterFailedAcquire判斷是否應該阻塞 * 前驅節點訊號量為-1,當前執行緒可以安全被parkAndCheckInterrupt用來阻塞執行緒 */ if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } /** * 與acquireQueued邏輯相似,唯一區別節點還不在隊列當中需要先進行入隊操作 */ private void doAcquireInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter(Node.EXCLUSIVE);//以獨佔模式放入佇列尾部 boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } /** * 獨佔模式定時獲取 */ private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException { if (nanosTimeout <= 0L) return false; final long deadline = System.nanoTime() + nanosTimeout; final Node node = addWaiter(Node.EXCLUSIVE);//加入佇列 boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return true; } nanosTimeout = deadline - System.nanoTime(); if (nanosTimeout <= 0L) return false;//超時直接返回獲取失敗 if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) //阻塞指定時長,超時則執行緒自動被喚醒 LockSupport.parkNanos(this, nanosTimeout); if (Thread.interrupted())//當前執行緒中斷狀態 throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } /** * 嘗試獲取共享鎖 */ private void doAcquireShared(int arg) { final Node node = addWaiter(Node.SHARED);//入隊 boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor();//前驅節點 if (p == head) { int r = tryAcquireShared(arg); //非公平鎖實現,再嘗試獲取鎖 //state==0時tryAcquireShared會返回>=0(CountDownLatch中返回的是1)。 // state為0說明共享次數已經到了,可以獲取鎖了 if (r >= 0) {//r>0表示state==0,前繼節點已經釋放鎖,鎖的狀態為可被獲取 //這一步設定node為head節點設定node.waitStatus->Node.PROPAGATE,然後喚醒node.thread setHeadAndPropagate(node, r); p.next = null; // help GC if (interrupted) selfInterrupt(); failed = false; return; } } //前繼節點非head節點,將前繼節點狀態設定為SIGNAL,通過park掛起node節點的執行緒 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } /** * Acquires in shared interruptible mode. * @param arg the acquire argument */ private void doAcquireSharedInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter(Node.SHARED); boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } /** * Acquires in shared timed mode. * * @param arg the acquire argument * @param nanosTimeout max wait time * @return {@code true} if acquired */ private boolean doAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException { if (nanosTimeout <= 0L) return false; final long deadline = System.nanoTime() + nanosTimeout; final Node node = addWaiter(Node.SHARED); boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC failed = false; return true; } } nanosTimeout = deadline - System.nanoTime(); if (nanosTimeout <= 0L) return false; if (shouldParkAfterFailedAcquire(p, node) && nanosTimeout > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); if (Thread.interrupted()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } // Main exported methods /** * 嘗試獲取獨佔鎖,可指定鎖的獲取數量 */ protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } /** * 嘗試釋放獨佔鎖,在子類當中實現 */ protected boolean tryRelease(int arg) { throw new UnsupportedOperationException(); } /** * 共享式:共享式地獲取同步狀態。對於獨佔式同步元件來講,同一時刻只有一個執行緒能獲取到同步狀態, * 其他執行緒都得去排隊等待,其待重寫的嘗試獲取同步狀態的方法tryAcquire返回值為boolean,這很容易理解; * 對於共享式同步元件來講,同一時刻可以有多個執行緒同時獲取到同步狀態,這也是“共享”的意義所在。 * 本方法待被之類覆蓋實現具體邏輯 * 1.當返回值大於0時,表示獲取同步狀態成功,同時還有剩餘同步狀態可供其他執行緒獲取; * * 2.當返回值等於0時,表示獲取同步狀態成功,但沒有可用同步狀態了; * 3.當返回值小於0時,表示獲取同步狀態失敗。 */ protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); } /** * 釋放共享鎖,具體實現在子類當中實現 */ protected boolean tryReleaseShared(int arg) { throw new UnsupportedOperationException(); } /** * 當前執行緒是否持有獨佔鎖 */ protected boolean isHeldExclusively() { throw new UnsupportedOperationException(); } /** * 獲取獨佔鎖 */ public final void acquire(int arg) { //嘗試獲取鎖 if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//獨佔模式 selfInterrupt(); } /** * */ public final void acquireInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (!tryAcquire(arg)) doAcquireInterruptibly(arg); } /** * 獲取獨佔鎖,設定最大等待時間 */ public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout); } /** * 釋放獨佔模式持有的鎖 */ public final boolean release(int arg) { if (tryRelease(arg)) {//釋放一次鎖 Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h);//喚醒後繼結點 return true; } return false; } /** * 請求獲取共享鎖 */ public final void acquireShared(int arg) { if (tryAcquireShared(arg) < 0)//返回值小於0,獲取同步狀態失敗,排隊去;獲取同步狀態成功,直接返回去幹自己的事兒。 doAcquireShared(arg); } /** * Releases in shared mode. Implemented by unblocking one or more * threads if {@link #tryReleaseShared} returns true. * * @param arg the release argument. This value is conveyed to * {@link #tryReleaseShared} but is otherwise uninterpreted * and can represent anything you like. * @return the value returned from {@link #tryReleaseShared} */ public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; } // Queue inspection methods public final boolean hasQueuedThreads() { return head != tail; } public final boolean hasContended() { return head != null; } public final Thread getFirstQueuedThread() { // handle only fast path, else relay return (head == tail) ? null : fullGetFirstQueuedThread(); } /** * Version of getFirstQueuedThread called when fastpath fails */ private Thread fullGetFirstQueuedThread() { Node h, s; Thread st; if (((h = head) != null && (s = h.next) != null && s.prev == head && (st = s.thread) != null) || ((h = head) != null && (s = h.next) != null && s.prev == head && (st = s.thread) != null)) return st; Node t = tail; Thread firstThread = null; while (t != null && t != head) { Thread tt = t.thread; if (tt != null) firstThread = tt; t = t.prev; } return firstThread; } /** * 判斷當前執行緒是否在隊列當中 */ public final boolean isQueued(Thread thread) { if (thread == null) throw new NullPointerException(); for (Node p = tail; p != null; p = p.prev) if (p.thread == thread) return true; return false; } final boolean apparentlyFirstQueuedIsExclusive() { Node h, s; return (h = head) != null && (s = h.next) != null && !s.isShared() && s.thread != null; } /** * 判斷當前節點是否有前驅節點 */ public final boolean hasQueuedPredecessors() { Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); } // Instrumentation and monitoring methods /** * 同步佇列長度 */ public final int getQueueLength() { int n = 0; for (Node p = tail; p != null; p = p.prev) { if (p.thread != null) ++n; } return n; } /** * 獲取佇列等待thread集合 */ public final Collection<Thread> getQueuedThreads() { ArrayList<Thread> list = new ArrayList<Thread>(); for (Node p = tail; p != null; p = p.prev) { Thread t = p.thread; if (t != null) list.add(t); } return list; } /** * 獲取獨佔模式等待thread執行緒集合 */ public final Collection<Thread> getExclusiveQueuedThreads() { ArrayList<Thread> list = new ArrayList<Thread>(); for (Node p = tail; p != null; p = p.prev) { if (!p.isShared()) { Thread t = p.thread; if (t != null) list.add(t); } } return list; } /** * 獲取共享模式等待thread集合 */ public final Collection<Thread> getSharedQueuedThreads() { ArrayList<Thread> list = new ArrayList<Thread>(); for (Node p = tail; p != null; p = p.prev) { if (p.isShared()) { Thread t = p.thread; if (t != null) list.add(t); } } return list; } // Internal support methods for Conditions /** * 判斷節點是否在同步佇列中 */ final boolean isOnSyncQueue(Node node) { //快速判斷1:節點狀態或者節點沒有前置節點 //注:同步佇列是有頭節點的,而條件佇列沒有 if (node.waitStatus == Node.CONDITION || node.prev == null) return false; //快速判斷2:next欄位只有同步佇列才會使用,條件佇列中使用的是nextWaiter欄位 if (node.next != null) // If has successor, it must be on queue return true; //上面如果無法判斷則進入複雜判斷 return findNodeFromTail(node); } private boolean findNodeFromTail(Node node) { Node t = tail; for (;;) { if (t == node) return true; if (t == null) return false; t = t.prev; } } /** * 將節點從條件隊列當中移動到同步隊列當中,等待獲取鎖 */ final boolean transferForSignal(Node node) { /* * 修改節點訊號量狀態為0,失敗直接返回false */ if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) return false; /* * 加入同步佇列尾部當中,返回前驅節點 */ Node p = enq(node); int ws = p.waitStatus; //前驅節點不可用 或者 修改訊號量狀態失敗 if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) LockSupport.unpark(node.thread); //喚醒當前節點 return true; } final boolean transferAfterCancelledWait(Node node) { if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) { enq(node); return true; } /* * If we lost out to a signal(), then we can't proceed * until it finishes its enq(). Cancelling during an * incomplete transfer is both rare and transient, so just * spin. */ while (!isOnSyncQueue(node)) Thread.yield(); return false; } /** * 入參就是新建立的節點,即當前節點 */ final int fullyRelease(Node node) { boolean failed = true; try { //這裡這個取值要注意,獲取當前的state並釋放,這從另一個角度說明必須是獨佔鎖 //可以考慮下這個邏輯放在共享鎖下面會發生什麼? int savedState = getState(); if (release(savedState)) { failed = false; return savedState; } else { //如果這裡釋放失敗,則丟擲異常 throw new IllegalMonitorStateException(); } } finally { /** * 如果釋放鎖失敗,則把節點取消,由這裡就能看出來上面新增節點的邏輯中 * 只需要判斷最後一個節點是否被取消就可以了 */ if (failed) node.waitStatus = Node.CANCELLED; } } // Instrumentation methods for conditions public final boolean hasWaiters(ConditionObject condition) { if (!owns(condition)) throw new IllegalArgumentException("Not owner"); return condition.hasWaiters(); } /** * 獲取條件佇列長度 */ public final int getWaitQueueLength(ConditionObject condition) { if (!owns(condition)) throw new IllegalArgumentException("Not owner"); return condition.getWaitQueueLength(); } /** * 獲取條件隊列當中所有等待的thread集合 */ public final Collection<Thread> getWaitingThreads(ConditionObject condition) { if (!owns(condition)) throw new IllegalArgumentException("Not owner"); return condition.getWaitingThreads(); } /** * 條件物件,實現基於條件的具體行為 */ public class ConditionObject implements Condition, java.io.Serializable { private static final long serialVersionUID = 1173984872572414699L; /** First node of condition queue. */ private transient Node firstWaiter; /** Last node of condition queue. */ private transient Node lastWaiter; /** * Creates a new {@code ConditionObject} instance. */ public ConditionObject() { } // Internal methods /** * 1.與同步佇列不同,條件佇列頭尾指標是firstWaiter跟lastWaiter * 2.條件佇列是在獲取鎖之後,也就是臨界區進行操作,因此很多地方不用考慮併發 */ private Node addConditionWaiter() { Node t = lastWaiter; //如果最後一個節點被取消,則刪除佇列中被取消的節點 //至於為啥是最後一個節點後面會分析 if (t != null && t.waitStatus != Node.CONDITION) { //刪除所有被取消的節點 unlinkCancelledWaiters(); t = lastWaiter; } //建立一個型別為CONDITION的節點並加入佇列,由於在臨界區,所以這裡不用併發控制 Node node = new Node(Thread.currentThread(), Node.CONDITION); if (t == null) firstWaiter = node; else t.nextWaiter = node; lastWaiter = node; return node; } /** * 發訊號,通知遍歷條件隊列當中的節點轉移到同步隊列當中,準備排隊獲取鎖 */ private void doSignal(Node first) { do { if ( (firstWaiter = first.nextWaiter) == null) lastWaiter = null; first.nextWaiter = null; } while (!transferForSignal(first) && //轉移節點 (first = firstWaiter) != null); } /** * 通知所有節點移動到同步隊列當中,並將節點從條件佇列刪除 */ private void doSignalAll(Node first) { lastWaiter = firstWaiter = null; do { Node next = first.nextWaiter; first.nextWaiter = null; transferForSignal(first); first = next; } while (first != null); } /** * 刪除條件隊列當中被取消的節點 */ private void unlinkCancelledWaiters() { Node t = firstWaiter; Node trail = null; while (t != null) { Node next = t.nextWaiter; if (t.waitStatus != Node.CONDITION) { t.nextWaiter = null; if (trail == null) firstWaiter = next; else trail.nextWaiter = next; if (next == null) lastWaiter = trail; } else trail = t; t = next; } } // public methods /** * 發新號,通知條件隊列當中節點到同步隊列當中去排隊 */ public final void signal() { if (!isHeldExclusively())//節點不能已經持有獨佔鎖 throw new IllegalMonitorStateException(); Node first = firstWaiter; if (first != null) /** * 發訊號通知條件佇列的節點準備到同步隊列當中去排隊 */ doSignal(first); } /** * 喚醒所有條件佇列的節點轉移到同步隊列當中 */ public final void signalAll() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); Node first = firstWaiter; if (first != null) doSignalAll(first); } /** * Implements uninterruptible condition wait. * <ol> * <li> Save lock state returned by {@link #getState}. * <li> Invoke {@link #release} with saved state as argument, * throwing IllegalMonitorStateException if it fails. * <li> Block until signalled. * <li> Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. * </ol> */ public final void awaitUninterruptibly() { Node node = addConditionWaiter(); int savedState = fullyRelease(node); boolean interrupted = false; while (!isOnSyncQueue(node)) { LockSupport.park(this); if (Thread.interrupted()) interrupted = true; } if (acquireQueued(node, savedState) || interrupted) selfInterrupt(); } /** 該模式表示在退出等待時重新中斷 */ private static final int REINTERRUPT = 1; /** 異常中斷 */ private static final int THROW_IE = -1; /** * 這裡的判斷邏輯是: * 1.如果現在不是中斷的,即正常被signal喚醒則返回0 * 2.如果節點由中斷加入同步佇列則返回THROW_IE,由signal加入同步佇列則返回REINTERRUPT */ private int checkInterruptWhileWaiting(Node node) { return Thread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0; } /** * 根據中斷時機選擇丟擲異常或者設定執行緒中斷狀態 */ private void reportInterruptAfterWait(int interruptMode) throws InterruptedException { if (interruptMode == THROW_IE) throw new InterruptedException(); else if (interruptMode == REINTERRUPT) selfInterrupt(); } /** * 加入條件佇列等待,條件佇列入口 */ public final void await() throws InterruptedException { //T2進來 //如果當前執行緒被中斷則直接丟擲異常 if (Thread.interrupted()) throw new InterruptedException(); //把當前節點加入條件佇列 Node node = addConditionWaiter(); //釋放掉已經獲取的獨佔鎖資源 int savedState = fullyRelease(node);//T2釋放鎖 int interruptMode = 0; //如果不在同步佇列中則不斷掛起 while (!isOnSyncQueue(node)) { LockSupport.park(this);//T1被阻塞 //這裡被喚醒可能是正常的signal操作也可能是中斷 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; } /** * 走到這裡說明節點已經條件滿足被加入到了同步佇列中或者中斷了 * 這個方法很熟悉吧?就跟獨佔鎖呼叫同樣的獲取鎖方法,從這裡可以看出條件佇列只能用於獨佔鎖 * 在處理中斷之前首先要做的是從同步佇列中成功獲取鎖資源 */ if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; //走到這裡說明已經成功獲取到了獨佔鎖,接下來就做些收尾工作 //刪除條件佇列中被取消的節點 if (node.nextWaiter != null) // clean up if cancelled unlinkCancelledWaiters(); //根據不同模式處理中斷 if (interruptMode != 0) reportInterruptAfterWait(interruptMode); } /** * Implements timed condition wait. * <ol> * <li> If current thread is interrupted, throw InterruptedException. * <li> Save lock state returned by {@link #getState}. * <li> Invoke {@link #release} with saved state as argument, * throwing IllegalMonitorStateException if it fails. * <li> Block until signalled, interrupted, or timed out. * <li> Reacquire by invoking specialized version of * {@link #acquire} with saved state as argument. * <li> If interrupted while blocked in step 4, throw InterruptedException. * <li> If timed out while blocked in step 4, return false, else true. * </ol> */ public final boolean await(long time, TimeUnit unit) throws InterruptedException { long nanosTimeout = unit.toNanos(time); if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); int savedState = fullyRelease(node); final long deadline = System.nanoTime() + nanosTimeout; boolean timedout = false; int interruptMode = 0; while (!isOnSyncQueue(node)) { if (nanosTimeout <= 0L) { timedout = transferAfterCancelledWait(node); break; } if (nanosTimeout >= spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; nanosTimeout = deadline - System.nanoTime(); } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; if (node.nextWaiter != null) unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); return !timedout; } final boolean isOwnedBy(AbstractQueuedSynchronizer sync) { return sync == AbstractQueuedSynchronizer.this; } /** * Queries whether any threads are waiting on this condition. * Implements {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}. * * @return {@code true} if there are any waiting threads * @throws IllegalMonitorStateException if {@link #isHeldExclusively} * returns {@code false} */ protected final boolean hasWaiters() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); for (Node w = firstWaiter; w != null; w = w.nextWaiter) { if (w.waitStatus == Node.CONDITION) return true; } return false; } /** * Returns an estimate of the number of threads waiting on * this condition. * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}. * * @return the estimated number of waiting threads * @throws IllegalMonitorStateException if {@link #isHeldExclusively} * returns {@code false} */ protected final int getWaitQueueLength() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); int n = 0; for (Node w = firstWaiter; w != null; w = w.nextWaiter) { if (w.waitStatus == Node.CONDITION) ++n; } return n; } /** * 得到同步隊列當中所有在等待的Thread集合 */ protected final Collection<Thread> getWaitingThreads() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); ArrayList<Thread> list = new ArrayList<Thread>(); for (Node w = firstWaiter; w != null; w = w.nextWaiter) { if (w.waitStatus == Node.CONDITION) { Thread t = w.thread; if (t != null) list.add(t); } } return list; } } /** * Setup to support compareAndSet. We need to natively implement * this here: For the sake of permitting future enhancements, we * cannot explicitly subclass AtomicInteger, which would be * efficient and useful otherwise. So, as the lesser of evils, we * natively implement using hotspot intrinsics API. And while we * are at it, we do the same for other CASable fields (which could * otherwise be done with atomic field updaters). * unsafe魔法類,直接繞過虛擬機器記憶體管理機制,修改記憶體 */ private static final Unsafe unsafe = Unsafe.getUnsafe(); //偏移量 private static final long stateOffset; private static final long headOffset; private static final long tailOffset; private static final long waitStatusOffset; private static final long nextOffset; static { try { //狀態偏移量 stateOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField("state")); //head指標偏移量,head指向CLH佇列的頭部 headOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField("head")); tailOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField("tail")); waitStatusOffset = unsafe.objectFieldOffset (Node.class.getDeclaredField("waitStatus")); nextOffset = unsafe.objectFieldOffset (Node.class.getDeclaredField("next")); } catch (Exception ex) { throw new Error(ex); } } /** * CAS 修改頭部節點指向. 併發入隊時使用. */ private final boolean compareAndSetHead(Node update) { return unsafe.compareAndSwapObject(this, headOffset, null, update); } /** * CAS 修改尾部節點指向. 併發入隊時使用. */ private final boolean compareAndSetTail(Node expect, Node update) { return unsafe.compareAndSwapObject(this, tailOffset, expect, update); } /** * CAS 修改訊號量狀態. */ private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) { return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update); } /** * 修改節點的後繼指標. */ private static final boolean compareAndSetNext(Node node, Node expect, Node update) { return unsafe.compareAndSwapObject(node, nextOffset, expect, update); } } AQS框架具體實現-獨佔鎖實現ReentrantLock public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; /** * 內部呼叫AQS的動作,都基於該成員屬性實現 */ private final Sync sync; /** * ReentrantLock鎖同步操作的基礎類,繼承自AQS框架. * 該類有兩個繼承類,1、NonfairSync 非公平鎖,2、FairSync公平鎖 */ abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; /** * 加鎖的具體行為由子類實現 */ abstract void lock(); /** * 嘗試獲取非公平鎖 */ final boolean nonfairTryAcquire(int acquires) { //acquires = 1 final Thread current = Thread.currentThread(); int c = getState(); /** * 不需要判斷同步佇列(CLH)中是否有排隊等待執行緒 * 判斷state狀態是否為0,不為0可以加鎖 */ if (c == 0) { //unsafe操作,cas修改state狀態 if (compareAndSetState(0, acquires)) { //獨佔狀態鎖持有者指向當前執行緒 setExclusiveOwnerThread(current); return true; } } /** * state狀態不為0,判斷鎖持有者是否是當前執行緒, * 如果是當前執行緒持有 則state+1 */ else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } //加鎖失敗 return false; } /** * 釋放鎖 */ protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } /** * 判斷持有獨佔鎖的執行緒是否是當前執行緒 */ protected final boolean isHeldExclusively() { return getExclusiveOwnerThread() == Thread.currentThread(); } //返回條件物件 final ConditionObject newCondition() { return new ConditionObject(); } final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } final boolean isLocked() { return getState() != 0; } /** * Reconstitutes the instance from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } /** * 非公平鎖 */ static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * 加鎖行為 */ final void lock() { /** * 第一步:直接嘗試加鎖 * 與公平鎖實現的加鎖行為一個最大的區別在於,此處不會去判斷同步佇列(CLH佇列)中 * 是否有排隊等待加鎖的節點,上來直接加鎖(判斷state是否為0,CAS修改state為1) * ,並將獨佔鎖持有者 exclusiveOwnerThread 屬性指向當前執行緒 * 如果當前有人佔用鎖,再嘗試去加一次鎖 */ if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else //AQS定義的方法,加鎖 acquire(1); } /** * 父類AbstractQueuedSynchronizer.acquire()中呼叫本方法 */ protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } /** * 公平鎖 */ static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } /** * 重寫aqs中的方法邏輯 * 嘗試加鎖,被AQS的acquire()方法呼叫 */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { /** * 與非公平鎖中的區別,需要先判斷隊列當中是否有等待的節點 * 如果沒有則可以嘗試CAS獲取鎖 */ if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { //獨佔執行緒指向當前執行緒 setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } } /** * 預設建構函式,建立非公平鎖物件 */ public ReentrantLock() { sync = new NonfairSync(); } /** * 根據要求建立公平鎖或非公平鎖 */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } /** * 加鎖 */ public void lock() { sync.lock(); } /** * 嘗試獲去取鎖,獲取失敗被阻塞,執行緒被中斷直接丟擲異常 */ public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } /** * 嘗試加鎖 */ public boolean tryLock() { return sync.nonfairTryAcquire(1); } /** * 指定等待時間內嘗試加鎖 */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } /** * 嘗試去釋放鎖 */ public void unlock() { sync.release(1); } /** * 返回條件物件 */ public Condition newCondition() { return sync.newCondition(); } /** * 返回當前執行緒持有的state狀態數量 */ public int getHoldCount() { return sync.getHoldCount(); } /** * 查詢當前執行緒是否持有鎖 */ public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } /** * 狀態表示是否被Thread加鎖持有 */ public boolean isLocked() { return sync.isLocked(); } /** * 是否公平鎖?是返回true 否則返回 false */ public final boolean isFair() { return sync instanceof FairSync; } /** * 獲取持有鎖的當前執行緒 */ protected Thread getOwner() { return sync.getOwner(); } /** * 判斷隊列當中是否有在等待獲取鎖的Thread節點 */ public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } /** * 當前執行緒是否在同步佇列中等待 */ public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); } /** * 獲取同步佇列長度 */ public final int getQueueLength() { return sync.getQueueLength(); } /** * 返回Thread集合,排隊中的所有節點Thread會被返回 */ protected Collection<Thread> getQueuedThreads() { return sync.getQueuedThreads(); } /** * 條件隊列當中是否有正在等待的節點 */ public boolean hasWaiters(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); } }