一、概念
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。又可分為公平鎖和非公平鎖:
公平鎖:按照線程在隊列中的排隊順序,先到者先拿到鎖
非公平鎖:當線程要獲取鎖時,無視隊列順序直接去搶鎖,誰搶到就是誰的,所以非公平鎖效率較高
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方法的整個的邏輯。邏輯如下:
判斷結點的前驅是否為head并且是否成功獲取(資源)。
若步驟1均滿足,則設置結點為head,之后會判斷是否finally模塊,然后返回。
若步驟2不滿足,則判斷是否需要park當前線程,是否需要park當前線程的邏輯是判斷結點的前驅結點的狀態是否為SIGNAL,若是,則park當前結點,否則,不進行park操作。
若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 getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList list = new ArrayList();
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();
}
原文鏈接:https://blog.csdn.net/tc979907461/article/details/105979761