併發鎖核心類AQS學習筆記

一、概念

AQS 是 AbstractQueuedSynchronizer 的簡稱,AQS 是一個抽象的隊列式同步器框架,提供了阻塞鎖和 FIFO 隊列實現同步操作。JUC 包中的同步類基本都是基於 AQS 同步器來實現的,如 ReentrantLock,Semaphore 等。

二、原理

1、AQS 工作機制:

  1. 如果被請求的共享資源空閒,則將當前請求資源的線程設置爲有效的工作線程,並且將共享資源設置爲鎖定狀態。
  2. 如果被請求的共享資源被佔用,則將獲取不到鎖的線程加入到隊列中。等到佔有線程釋放鎖後喚醒隊列中的任務爭搶鎖,這個隊列爲 CLH 隊列。
  3. 使用state成員變量表示當前的同步狀態,提供 getState,setState,compareAndSetState 進行操作。

2、CLH 隊列:

虛擬的雙向隊列,底層是雙向鏈表,包括head結點和tail結點,僅存在結點之間的關聯關係。AQS將每條請求共享資源的線程封裝成一個CLH鎖隊列的一個結點(Node)來實現鎖的分配。
在這裏插入圖片描述

3、AQS 對資源的共享方式

AQS定義兩種資源共享方式

  1. 獨佔 ( Exclusive ):只有一個線程能執行,如 ReentrantLock。又可分爲公平鎖和非公平鎖:
    1. 公平鎖:按照線程在隊列中的排隊順序,先到者先拿到鎖
    2. 非公平鎖:當線程要獲取鎖時,無視隊列順序直接去搶鎖,誰搶到就是誰的,所以非公平鎖效率較高
  2. 共享 ( Share ):多個線程可同時執行,如Semaphore、CountDownLatch。

4、AQS 的設計模式

AQS 同步器的設計是基於模板方法模式。使用者繼承AbstractQueuedSynchronizer並重寫指定的方法。實現對於共享資源state的獲取和釋放。
將AQS組合在自定義同步組件的實現中,並調用其模板方法,而這些模板方法會調用使用者重寫的方法。 AQS類中的其他方法都是final ,所以無法被其他類使用,只有這幾個方法可以被其他類使用,自定義同步器時需要重寫下面幾個AQS提供的模板方法:

isHeldExclusively()//該線程是否正在獨佔資源。只有用到condition才需要去實現它。
tryAcquire(int)//獨佔方式。嘗試獲取資源,成功則返回true,失敗則返回false。
tryRelease(int)//獨佔方式。嘗試釋放資源,成功則返回true,失敗則返回false。
tryAcquireShared(int)//共享方式。嘗試獲取資源。負數表示失敗;0表示成功,但沒有剩餘可用資源;正數表示成功,且有剩餘資源。
tryReleaseShared(int)//共享方式。嘗試釋放資源,成功則返回true,失敗則返回false。

以 ReentrantLock爲 例,state初始化爲0,表示未鎖定狀態。A線程lock()時,會調用tryAcquire()獨佔該鎖並將state+1。此後,其他線程再tryAcquire()時就會失敗,直到A線程unlock()到state=0(即釋放鎖)爲止,其它線程纔有機會獲取該鎖。當然,釋放鎖之前,A線程自己是可以重複獲取此鎖的(state會累加),這就是可重入的概念。但要注意,獲取多少次就要釋放多麼次,這樣才能保證state是能回到零態的。

三、空間結構

AbstractQueuedSynchronizer繼承自AbstractOwnableSynchronizer抽象類,並且實現了Serializable接口,可以進行序列化。

 AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable

隊列中Node的頭結點

private transient volatile Node head;    

隊列中Node的尾結點

private transient volatile Node tail;  

表示同步狀態的成員變量,使用volatile修飾保證線程可見性

private volatile int state;

返回同步狀態的當前值

protected final int getState() {  
        return state;
}

設置同步狀態的值

protected final void setState(int newState) { 
        state = newState;
}

原子地(CAS操作)將同步狀態值設置爲給定值update如果當前同步狀態的值等於expect(期望值)

protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

自旋時間

static final long spinForTimeoutThreshold = 1000L;

Unsafe類實例

private static final Unsafe unsafe = Unsafe.getUnsafe();

state內存偏移地址

private static final long stateOffset;

head內存偏移地址

private static final long headOffset;

tail內存偏移地址

private static final long tailOffset;

節點狀態內存偏移地址

private static final long waitStatusOffset;

next內存偏移地址

private static final long nextOffset;

靜態初始化塊,用於加載內存偏移地址。

static {
        try {
            stateOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
            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); }
}

類構造方法爲從抽象構造方法,供子類調用。

protected AbstractQueuedSynchronizer() { }    

四、常用方法

acquire
該方法以獨佔模式獲取資源,先嚐試獲取鎖,如果獲取失敗則調用addWaiter將該線程加入隊列中,。源碼如下:

 public final void acquire(int arg) {
    if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

由上述源碼可以知道,當一個線程調用acquire時,調用方法流程如下
在這裏插入圖片描述

  1. 首先調用tryAcquire方法,調用此方法的線程會試圖在獨佔模式下獲取對象狀態。此方法應該查詢是否允許它在獨佔模式下獲取對象狀態,如果允許,則獲取它。在AbstractQueuedSynchronizer源碼中默認會拋出一個異常,即需要子類去重寫此方法完成自己的邏輯。之後會進行分析。
  2. 若tryAcquire失敗,則調用addWaiter方法,addWaiter方法完成的功能是將調用此方法的線程封裝成爲一個結點並放入Sync queue。
  3. 調用acquireQueued方法,此方法完成的功能是Sync queue中的結點不斷嘗試獲取資源,若成功,則返回true,否則,返回false。
  4. 由於tryAcquire默認實現是拋出異常,所以此時,不進行分析,之後會結合一個例子進行分析。

addWaiter
使用快速添加的方式往sync queue尾部添加結點,如果sync queue隊列還沒有初始化,則會使用enq插入隊列中。

// 添加等待者
private Node addWaiter(Node mode) {
    // 新生成一個結點,默認爲獨佔模式
    Node node = new Node(Thread.currentThread(), mode);
    // Try the fast path of enq; backup to full enq on failure
    // 保存尾結點
    Node pred = tail;
    if (pred != null) { // 尾結點不爲空,即已經被初始化
        // 將node結點的prev域連接到尾結點
        node.prev = pred; 
        if (compareAndSetTail(pred, node)) { // 比較pred是否爲尾結點,是則將尾結點設置爲node 
            // 設置尾結點的next域爲node
            pred.next = node;
            return node; // 返回新生成的結點
        }
    }
    enq(node); // 尾結點爲空(即還沒有被初始化過),或者是compareAndSetTail操作失敗,則入隊列
    return node;
}

enq
使用無限循環來確保節點的成功插入。

private Node enq(final Node node) {
    for (;;) { // 無限循環,確保結點能夠成功入隊列
        // 保存尾結點
        Node t = tail;
        if (t == null) { // 尾結點爲空,即還沒被初始化
            if (compareAndSetHead(new Node())) // 頭結點爲空,並設置頭結點爲新生成的結點
                tail = head; // 頭結點與尾結點都指向同一個新生結點
        } else { // 尾結點不爲空,即已經被初始化過
            // 將node結點的prev域連接到尾結點
            node.prev = t; 
            if (compareAndSetTail(t, node)) { // 比較結點t是否爲尾結點,若是則將尾結點設置爲node
                // 設置尾結點的next域爲node
                t.next = node; 
                return t; // 返回尾結點
            }
        }
    }
}

acquireQueue
首先獲取當前節點的前驅節點,如果前驅節點是頭結點並且能夠獲取(資源),代表該當前節點能夠佔有鎖,設置頭結點爲當前節點,返回。否則,調用shouldParkAfterFailedAcquire和parkAndCheckInterrupt方法

// sync隊列中的結點在獨佔且忽略中斷的模式下獲取(資源)
final boolean acquireQueued(final Node node, int arg) {
    // 標誌
    boolean failed = true;
    try {
        // 中斷標誌
        boolean interrupted = false;
        for (;;) { // 無限循環
            // 獲取node節點的前驅結點
            final Node p = node.predecessor(); 
            if (p == head && tryAcquire(arg)) { // 前驅爲頭結點並且成功獲得鎖
                setHead(node); // 設置頭結點
                p.next = null; // help GC
                failed = false; // 設置標誌
                return interrupted; 
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

shouldParkAfterFailedAcquire和方法,首先,我們看

shouldParkAfterFailedAcquire
只有當該節點的前驅結點的狀態爲SIGNAL時,纔可以對該結點所封裝的線程進行park操作。否則,將不能進行park操作。

// 當獲取(資源)失敗後,檢查並且更新結點狀態
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    // 獲取前驅結點的狀態
    int ws = pred.waitStatus;
    if (ws == Node.SIGNAL) // 狀態爲SIGNAL,爲-1
        // 可以進行park操作
        return true; 
    if (ws > 0) { // 表示狀態爲CANCELLED,爲1
        do {
            node.prev = pred = pred.prev;
        } while (pred.waitStatus > 0); // 找到pred結點前面最近的一個狀態不爲CANCELLED的結點
        // 賦值pred結點的next域
        pred.next = node; 
    } else { // 爲PROPAGATE -3 或者是0 表示無狀態,(爲CONDITION -2時,表示此節點在condition queue中) 
        // 比較並設置前驅結點的狀態爲SIGNAL
        compareAndSetWaitStatus(pred, ws, Node.SIGNAL); 
    }
    // 不能進行park操作
    return false;
}

parkAndCheckInterrupt

首先執行park操作,即禁用當前線程,然後返回該線程是否已經被中斷

// 進行park操作並且返回該線程是否被中斷
private final boolean parkAndCheckInterrupt() {
    // 在許可可用之前禁用當前線程,並且設置了blocker
    LockSupport.park(this);
    return Thread.interrupted(); // 當前線程是否已被中斷,並清除中斷標記位
}

cancelAcquire
該方法完成的功能就是取消當前線程對資源的獲取,即設置該結點的狀態爲CANCELLED

// 取消繼續獲取(資源)
private void cancelAcquire(Node node) {
    // Ignore if node doesn't exist
    // node爲空,返回
    if (node == null)
        return;
    // 設置node結點的thread爲空
    node.thread = null;

    // Skip cancelled predecessors
    // 保存node的前驅結點
    Node pred = node.prev;
    while (pred.waitStatus > 0) // 找到node前驅結點中第一個狀態小於0的結點,即不爲CANCELLED狀態的結點
        node.prev = pred = pred.prev;
    // 獲取pred結點的下一個結點
    Node predNext = pred.next;
    // 設置node結點的狀態爲CANCELLED
    node.waitStatus = Node.CANCELLED;

    // If we are the tail, remove ourselves.
    if (node == tail && compareAndSetTail(node, pred)) { // node結點爲尾結點,則設置尾結點爲pred結點
        // 比較並設置pred結點的next節點爲null
        compareAndSetNext(pred, predNext, null); 
    } else { // node結點不爲尾結點,或者比較設置不成功
   
        int ws;
        if (pred != head &&
            ((ws = pred.waitStatus) == Node.SIGNAL ||
                (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
            pred.thread != null) { // (pred結點不爲頭結點,並且pred結點的狀態爲SIGNAL)或者 
                                // pred結點狀態小於等於0,並且比較並設置等待狀態爲SIGNAL成功,並且pred結點所封裝的線程不爲空
            // 保存結點的後繼
            Node next = node.next;
            if (next != null && next.waitStatus <= 0) // 後繼不爲空並且後繼的狀態小於等於0
                compareAndSetNext(pred, predNext, next); // 比較並設置pred.next = next;
        } else {
            unparkSuccessor(node); // 釋放node的前一個結點
        }

        node.next = node; // help GC
    }
}

unparkSuccessor
該方法的作用就是爲了釋放node節點的後繼結點。

 // 釋放後繼結點
private void unparkSuccessor(Node node) {
    // 獲取node結點的等待狀態
    int ws = node.waitStatus;
    if (ws < 0) // 狀態值小於0,爲SIGNAL -1 或 CONDITION -2 或 PROPAGATE -3
        // 比較並且設置結點等待狀態,設置爲0
        compareAndSetWaitStatus(node, ws, 0);
    // 獲取node節點的下一個結點
    Node s = node.next;
    if (s == null || s.waitStatus > 0) { // 下一個結點爲空或者下一個節點的等待狀態大於0,即爲CANCELLED
        // s賦值爲空
        s = null; 
        // 從尾結點開始從後往前開始遍歷
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0) // 找到等待狀態小於等於0的結點,找到最前的狀態小於等於0的結點
                // 保存結點
                s = t;
    }
    if (s != null) // 該結點不爲爲空,釋放許可
        LockSupport.unpark(s.thread);
}

對於cancelAcquire與unparkSuccessor方法,如下示意圖可以清晰的表示:
在這裏插入圖片描述

其中node爲參數,在執行完cancelAcquire方法後的效果就是unpark了s結點所包含的t4線程。

現在,再來看acquireQueued方法的整個的邏輯。邏輯如下:

  1. 判斷結點的前驅是否爲head並且是否成功獲取(資源)。
  2. 若步驟1均滿足,則設置結點爲head,之後會判斷是否finally模塊,然後返回。
  3. 若步驟2不滿足,則判斷是否需要park當前線程,是否需要park當前線程的邏輯是判斷結點的前驅結點的狀態是否爲SIGNAL,若是,則park當前結點,否則,不進行park操作。
  4. 若park了當前線程,之後某個線程對本線程unpark後,並且本線程也獲得機會運行。那麼,將會繼續進行步驟①的判斷。

release
以獨佔模式釋放對象,其中 tryRelease 的默認實現是拋出異常,需要具體的子類實現,如果 tryRelease 成功,那麼如果頭結點不爲空並且頭結點的狀態不爲 0,則釋放頭結點的後繼結點。

public final boolean release(int arg) {
    if (tryRelease(arg)) { // 釋放成功
        // 保存頭結點
        Node h = head; 
        if (h != null && h.waitStatus != 0) // 頭結點不爲空並且頭結點狀態不爲0
            unparkSuccessor(h); //釋放頭結點的後繼結點
        return true;
    }
    return false;
}

五、內部類

Node類

每個線程被阻塞的線程都會被封裝成一個Node結點,放入隊列。每個節點包含了一個Thread類型的引用,並且每個節點都存在一個狀態,具體狀態如下。

  1. CANCELLED,值爲1,表示當前的線程被取消。
  2. SIGNAL,值爲-1,表示當前節點的後繼節點包含的線程需要運行,需要進行unpark操作。
  3. CONDITION,值爲-2,表示當前節點在等待condition,也就是在condition queue中。
  4. PROPAGATE,值爲-3,表示當前場景下後續的acquireShared能夠得以執行。
  5. 值爲0,表示當前節點在sync queue中,等待着獲取鎖。
 static final class Node {
    // 模式,分爲共享與獨佔
    // 共享模式
    static final Node SHARED = new Node();
    // 獨佔模式
    static final Node EXCLUSIVE = null;        
    // 結點狀態
    // CANCELLED,值爲1,表示當前的線程被取消
    // SIGNAL,值爲-1,表示當前節點的後繼節點包含的線程需要運行,也就是unpark
    // CONDITION,值爲-2,表示當前節點在等待condition,也就是在condition隊列中
    // PROPAGATE,值爲-3,表示當前場景下後續的acquireShared能夠得以執行
    // 值爲0,表示當前節點在sync隊列中,等待着獲取鎖
    static final int CANCELLED =  1;
    static final int SIGNAL    = -1;
    static final int CONDITION = -2;
    static final int PROPAGATE = -3;        

    // 結點狀態
    volatile int waitStatus;        
    // 前驅結點
    volatile Node prev;    
    // 後繼結點
    volatile Node next;        
    // 結點所對應的線程
    volatile Thread thread;        
    // 下一個等待者
    Node nextWaiter;
    
    // 結點是否在共享模式下等待
    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
    }
    
    // 構造方法
        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;
    }
}

ConditionObject類

// 內部類
public class ConditionObject implements Condition, java.io.Serializable {
    // 版本號
    private static final long serialVersionUID = 1173984872572414699L;
    // condition隊列的頭結點
    private transient Node firstWaiter;
    // condition隊列的尾結點
    private transient Node lastWaiter;
    // 構造方法
    public ConditionObject() { }
    // 添加新的waiter到wait隊列
    private Node addConditionWaiter() {
        // 保存尾結點
        Node t = lastWaiter;
        // 尾結點不爲空,並且尾結點的狀態不爲CONDITION
        if (t != null && t.waitStatus != Node.CONDITION) { 
            // 清除狀態爲CONDITION的結點
            unlinkCancelledWaiters(); 
            // 將最後一個結點重新賦值給t
            t = lastWaiter;
        }
        // 新建一個結點
        Node node = new Node(Thread.currentThread(), Node.CONDITION);
        if (t == null) // 尾結點爲空
            // 設置condition隊列的頭結點
            firstWaiter = node;
        else // 尾結點不爲空
            // 設置爲節點的nextWaiter域爲node結點
            t.nextWaiter = node;
        // 更新condition隊列的尾結點
        lastWaiter = node;
        return node;
    }

    private void doSignal(Node first) {
        // 循環
        do {
            if ( (firstWaiter = first.nextWaiter) == null) // 該節點的nextWaiter爲空
                // 設置尾結點爲空
                lastWaiter = null;
            // 設置first結點的nextWaiter域
            first.nextWaiter = null;
        } while (!transferForSignal(first) &&
                    (first = firstWaiter) != null); // 將結點從condition隊列轉移到sync隊列失敗並且condition隊列中的頭結點不爲空,一直循環
    }

    private void doSignalAll(Node first) {
        // condition隊列的頭結點尾結點都設置爲空
        lastWaiter = firstWaiter = null;
        // 循環
        do {
            // 獲取first結點的nextWaiter域結點
            Node next = first.nextWaiter;
            // 設置first結點的nextWaiter域爲空
            first.nextWaiter = null;
            // 將first結點從condition隊列轉移到sync隊列
            transferForSignal(first);
            // 重新設置first
            first = next;
        } while (first != null);
    }

    // 從condition隊列中清除狀態爲CANCEL的結點
    private void unlinkCancelledWaiters() {
        // 保存condition隊列頭結點
        Node t = firstWaiter;
        Node trail = null;
        while (t != null) { // t不爲空
            // 下一個結點
            Node next = t.nextWaiter;
            if (t.waitStatus != Node.CONDITION) { // t結點的狀態不爲CONDTION狀態
                // 設置t節點的額nextWaiter域爲空
                t.nextWaiter = null;
                if (trail == null) // trail爲空
                    // 重新設置condition隊列的頭結點
                    firstWaiter = next;
                else // trail不爲空
                    // 設置trail結點的nextWaiter域爲next結點
                    trail.nextWaiter = next;
                if (next == null) // next結點爲空
                    // 設置condition隊列的尾結點
                    lastWaiter = trail;
            }
            else // t結點的狀態爲CONDTION狀態
                // 設置trail結點
                trail = t;
            // 設置t結點
            t = next;
        }
    }

    // 喚醒一個等待線程。如果所有的線程都在等待此條件,則選擇其中的一個喚醒。在從 await 返回之前,該線程必須重新獲取鎖。
    public final void signal() {
        if (!isHeldExclusively()) // 不被當前線程獨佔,拋出異常
            throw new IllegalMonitorStateException();
        // 保存condition隊列頭結點
        Node first = firstWaiter;
        if (first != null) // 頭結點不爲空
            // 喚醒一個等待線程
            doSignal(first);
    }

    // 喚醒所有等待線程。如果所有的線程都在等待此條件,則喚醒所有線程。在從 await 返回之前,每個線程都必須重新獲取鎖。
    public final void signalAll() {
        if (!isHeldExclusively()) // 不被當前線程獨佔,拋出異常
            throw new IllegalMonitorStateException();
        // 保存condition隊列頭結點
        Node first = firstWaiter;
        if (first != null) // 頭結點不爲空
            // 喚醒所有等待線程
            doSignalAll(first);
    }

    // 等待,當前線程在接到信號之前一直處於等待狀態,不響應中斷
    public final void awaitUninterruptibly() {
        // 添加一個結點到等待隊列
        Node node = addConditionWaiter();
        // 獲取釋放的狀態
        int savedState = fullyRelease(node);
        boolean interrupted = false;
        while (!isOnSyncQueue(node)) { // 
            // 阻塞當前線程
            LockSupport.park(this);
            if (Thread.interrupted()) // 當前線程被中斷
                // 設置interrupted狀態
                interrupted = true; 
        }
        if (acquireQueued(node, savedState) || interrupted) 
            selfInterrupt();
    }
 
    private static final int REINTERRUPT =  1;
    private static final int THROW_IE    = -1;
    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 {
        if (Thread.interrupted()) // 當前線程被中斷,拋出異常
            throw new InterruptedException();
        // 在wait隊列上添加一個結點
        Node node = addConditionWaiter(); 
        int savedState = fullyRelease(node);
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            // 阻塞當前線程
            LockSupport.park(this);
            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);
    }

    // 等待,當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態 
    public final long awaitNanos(long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                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 deadline - System.nanoTime();
    }
    // 等待,當前線程在接到信號、被中斷或到達指定最後期限之前一直處於等待狀態
    public final boolean awaitUntil(Date deadline)
            throws InterruptedException {
        long abstime = deadline.getTime();
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (System.currentTimeMillis() > abstime) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            LockSupport.parkUntil(this, abstime);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }

 
    // 等待,當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。此方法在行爲上等效於: awaitNanos(unit.toNanos(time)) > 0
    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;
    }

    //  查詢是否有正在等待此條件的任何線程
    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;
    }

    // 返回正在等待此條件的線程數估計值
    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;
    }

    // 返回包含那些可能正在等待此條件的線程集合
    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;
    }
}

此類實現了Condition接口,Condition接口定義了條件操作規範,具體如下

public interface Condition {

    // 等待,當前線程在接到信號或被中斷之前一直處於等待狀態
    void await() throws InterruptedException;
    
    // 等待,當前線程在接到信號之前一直處於等待狀態,不響應中斷
    void awaitUninterruptibly();
    
    //等待,當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態 
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    
    // 等待,當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。此方法在行爲上等效於: awaitNanos(unit.toNanos(time)) > 0
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    
    // 等待,當前線程在接到信號、被中斷或到達指定最後期限之前一直處於等待狀態
    boolean awaitUntil(Date deadline) throws InterruptedException;
    
    // 喚醒一個等待線程。如果所有的線程都在等待此條件,則選擇其中的一個喚醒。在從 await 返回之前,該線程必須重新獲取鎖。
    void signal();
    
    // 喚醒所有等待線程。如果所有的線程都在等待此條件,則喚醒所有線程。在從 await 返回之前,每個線程都必須重新獲取鎖。
    void signalAll();
}

Condition接口中定義了await、signal方法,用來等待條件、釋放條件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章