轉(zhuǎn)?https://mp.weixin.qq.com/s/-O2qJTOizvbl7gx1RtFGjQ
通過(guò)前面三篇的分析,我們深入了解了 AbstractQueuedSynchronizer 的內(nèi)部結(jié)構(gòu)和一些設(shè)計(jì)理念,知道了 AbstractQueuedSynchronizer 內(nèi)部維護(hù)了一個(gè)同步狀態(tài)和兩個(gè)排隊(duì)區(qū),這兩個(gè)排隊(duì)區(qū)分別是同步隊(duì)列和條件隊(duì)列。
我們還是拿公共廁所做比喻,同步隊(duì)列是主要的排隊(duì)區(qū),如果公共廁所沒(méi)開(kāi)放,所有想要進(jìn)入廁所的人都得在這里排隊(duì)。而條件隊(duì)列主要是為條件等待設(shè)置的,我們想象一下如果一個(gè)人通過(guò)排隊(duì)終于成功獲取鎖進(jìn)入了廁所,但在方便之前發(fā)現(xiàn)自己沒(méi)帶手紙,碰到這種情況雖然很無(wú)奈,但是它也必須接受這個(gè)事實(shí),這時(shí)它只好乖乖的出去先準(zhǔn)備好手紙 (進(jìn)入條件隊(duì)列等待),當(dāng)然在出去之前還得把鎖給釋放了好讓其他人能夠進(jìn)來(lái),在準(zhǔn)備好了手紙 (條件滿足) 之后它又得重新回到同步隊(duì)列中去排隊(duì)。
當(dāng)然進(jìn)入房間的人并不都是因?yàn)闆](méi)帶手紙,可能還有其他一些原因必須中斷操作先去條件隊(duì)列中去排隊(duì),所以條件隊(duì)列可以有多個(gè),依不同的等待條件而設(shè)置不同的條件隊(duì)列。條件隊(duì)列是一條單向鏈表,Condition 接口定義了條件隊(duì)列中的所有操作,AbstractQueuedSynchronizer 內(nèi)部的 ConditionObject 類實(shí)現(xiàn)了 Condition 接口。
下面我們看看 Condition 接口都定義了哪些操作。
publicinterfaceCondition{
//響應(yīng)線程中斷的條件等待
voidawait()throwsInterruptedException;
//不響應(yīng)線程中斷的條件等待
voidawaitUninterruptibly();
//設(shè)置相對(duì)時(shí)間的條件等待(不進(jìn)行自旋)
longawaitNanos(longnanosTimeout)throwsInterruptedException;
//設(shè)置相對(duì)時(shí)間的條件等待(進(jìn)行自旋)
booleanawait(longtime, TimeUnit unit)throwsInterruptedException;
//設(shè)置絕對(duì)時(shí)間的條件等待
booleanawaitUntil(Date deadline)throwsInterruptedException;
//喚醒條件隊(duì)列中的頭結(jié)點(diǎn)
voidsignal();
//喚醒條件隊(duì)列的所有結(jié)點(diǎn)
voidsignalAll();
}
Condition 接口雖然定義了這么多方法,但總共就分為兩類,以 await 開(kāi)頭的是線程進(jìn)入條件隊(duì)列等待的方法,以 signal 開(kāi)頭的是將條件隊(duì)列中的線程 “喚醒” 的方法。這里要注意的是,調(diào)用 signal 方法可能喚醒線程也可能不會(huì)喚醒線程,什么時(shí)候會(huì)喚醒線程這得看情況,后面會(huì)講到,但是調(diào)用 signal 方法一定會(huì)將線程從條件隊(duì)列中移到同步隊(duì)列尾部。
這里為了敘述方便,我們先暫時(shí)不糾結(jié)這么多,統(tǒng)一稱 signal 方法為喚醒條件隊(duì)列線程的操作。大家注意看一下,await 方法分為 5 種,分別是響應(yīng)線程中斷等待,不響應(yīng)線程中斷等待,設(shè)置相對(duì)時(shí)間不自旋等待,設(shè)置相對(duì)時(shí)間自旋等待,設(shè)置絕對(duì)時(shí)間等待;signal 方法只有 2 種,分別是只喚醒條件隊(duì)列頭結(jié)點(diǎn)和喚醒條件隊(duì)列所有結(jié)點(diǎn)的操作。
同一類的方法基本上是相通的,由于篇幅所限,我們不可能也不需要將這些方法全部仔細(xì)的講到,只需要將一個(gè)代表方法搞懂了再看其他方法就能夠觸類旁通。所以在本文中我只會(huì)細(xì)講 await 方法和 signal 方法,其他方法不細(xì)講但會(huì)貼出源碼來(lái)以供大家參考。
1. 響應(yīng)線程中斷的條件等待
//響應(yīng)線程中斷的條件等待
publicfinalvoidawait()throwsInterruptedException{
//如果線程被中斷則拋出異常
if(Thread.interrupted()) {
thrownewInterruptedException();
}
//將當(dāng)前線程添加到條件隊(duì)列尾部
Node node = addConditionWaiter();
//在進(jìn)入條件等待之前先完全釋放鎖
intsavedState = fullyRelease(node);
intinterruptMode =0;
//線程一直在while循環(huán)里進(jìn)行條件等待
while(!isOnSyncQueue(node)) {
//進(jìn)行條件等待的線程都在這里被掛起, 線程被喚醒的情況有以下幾種:
//1.同步隊(duì)列的前繼結(jié)點(diǎn)已取消
//2.設(shè)置同步隊(duì)列的前繼結(jié)點(diǎn)的狀態(tài)為SIGNAL失敗
//3.前繼結(jié)點(diǎn)釋放鎖后喚醒當(dāng)前結(jié)點(diǎn)
LockSupport.park(this);
//當(dāng)前線程醒來(lái)后立馬檢查是否被中斷, 如果是則代表結(jié)點(diǎn)取消條件等待, 此時(shí)需要將結(jié)點(diǎn)移出條件隊(duì)列
if((interruptMode = checkInterruptWhileWaiting(node)) !=0) {
break;
}
}
//線程醒來(lái)后就會(huì)以獨(dú)占模式獲取鎖
if(acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
//這步操作主要為防止線程在signal之前中斷而導(dǎo)致沒(méi)與條件隊(duì)列斷絕聯(lián)系
if(node.nextWaiter !=null) {
unlinkCancelledWaiters();
}
//根據(jù)中斷模式進(jìn)行響應(yīng)的中斷處理
if(interruptMode !=0) {
reportInterruptAfterWait(interruptMode);
}
}
當(dāng)線程調(diào)用 await 方法的時(shí)候,首先會(huì)將當(dāng)前線程包裝成 node 結(jié)點(diǎn)放入條件隊(duì)列尾部。在 addConditionWaiter 方法中,如果發(fā)現(xiàn)條件隊(duì)列尾結(jié)點(diǎn)已取消就會(huì)調(diào)用 unlinkCancelledWaiters 方法將條件隊(duì)列所有的已取消結(jié)點(diǎn)清空。
這步操作是插入結(jié)點(diǎn)的準(zhǔn)備工作,那么確保了尾結(jié)點(diǎn)的狀態(tài)也是 CONDITION 之后,就會(huì)新建一個(gè) node 結(jié)點(diǎn)將當(dāng)前線程包裝起來(lái)然后放入條件隊(duì)列尾部。注意,這個(gè)過(guò)程只是將結(jié)點(diǎn)添加到同步隊(duì)列尾部而沒(méi)有掛起線程哦。
第二步:完全將鎖釋放
//完全釋放鎖
finalintfullyRelease(Node node){
booleanfailed =true;
try{
//獲取當(dāng)前的同步狀態(tài)
intsavedState = getState();
//使用當(dāng)前的同步狀態(tài)去釋放鎖
if(release(savedState)) {
failed =false;
//如果釋放鎖成功就返回當(dāng)前同步狀態(tài)
returnsavedState;
}else{
//如果釋放鎖失敗就拋出運(yùn)行時(shí)異常
thrownewIllegalMonitorStateException();
}
}finally{
//保證沒(méi)有成功釋放鎖就將該結(jié)點(diǎn)設(shè)置為取消狀態(tài)
if(failed) {
node.waitStatus = Node.CANCELLED;
}
}
}
將當(dāng)前線程包裝成結(jié)點(diǎn)添加到條件隊(duì)列尾部后,緊接著就調(diào)用 fullyRelease 方法釋放鎖。注意,方法名為 fullyRelease 也就這步操作會(huì)完全的釋放鎖,因?yàn)殒i是可重入的,所以在進(jìn)行條件等待前需要將鎖全部釋放了,不然的話別人就獲取不了鎖了。如果釋放鎖失敗的話就會(huì)拋出一個(gè)運(yùn)行時(shí)異常,如果成功釋放了鎖的話就返回之前的同步狀態(tài)。
第三步:進(jìn)行條件等待
//線程一直在while循環(huán)里進(jìn)行條件等待
while(!isOnSyncQueue(node)) {
//進(jìn)行條件等待的線程都在這里被掛起, 線程被喚醒的情況有以下幾種:
//1.同步隊(duì)列的前繼結(jié)點(diǎn)已取消
//2.設(shè)置同步隊(duì)列的前繼結(jié)點(diǎn)的狀態(tài)為SIGNAL失敗
//3.前繼結(jié)點(diǎn)釋放鎖后喚醒當(dāng)前結(jié)點(diǎn)
LockSupport.park(this);
//當(dāng)前線程醒來(lái)后立馬檢查是否被中斷, 如果是則代表結(jié)點(diǎn)取消條件等待, 此時(shí)需要將結(jié)點(diǎn)移出條件隊(duì)列
if((interruptMode = checkInterruptWhileWaiting(node)) !=0) {
break;
}
}
//檢查條件等待時(shí)的線程中斷情況
privateintcheckInterruptWhileWaiting(Node node){
//中斷請(qǐng)求在signal操作之前:THROW_IE
//中斷請(qǐng)求在signal操作之后:REINTERRUPT
//期間沒(méi)有收到任何中斷請(qǐng)求:0
returnThread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :0;
}
//將取消條件等待的結(jié)點(diǎn)從條件隊(duì)列轉(zhuǎn)移到同步隊(duì)列中
finalbooleantransferAfterCancelledWait(Node node){
//如果這步CAS操作成功的話就表明中斷發(fā)生在signal方法之前
if(compareAndSetWaitStatus(node, Node.CONDITION,0)) {
//狀態(tài)修改成功后就將該結(jié)點(diǎn)放入同步隊(duì)列尾部
enq(node);
returntrue;
}
//到這里表明CAS操作失敗, 說(shuō)明中斷發(fā)生在signal方法之后
while(!isOnSyncQueue(node)) {
//如果sinal方法還沒(méi)有將結(jié)點(diǎn)轉(zhuǎn)移到同步隊(duì)列, 就通過(guò)自旋等待一下
Thread.yield();
}
returnfalse;
}
在以上兩個(gè)操作完成了之后就會(huì)進(jìn)入 while 循環(huán),可以看到 while 循環(huán)里面首先調(diào)用 LockSupport.park (this) 將線程掛起了,所以線程就會(huì)一直在這里阻塞。在調(diào)用 signal 方法后僅僅只是將結(jié)點(diǎn)從條件隊(duì)列轉(zhuǎn)移到同步隊(duì)列中去,至于會(huì)不會(huì)喚醒線程需要看情況。
如果轉(zhuǎn)移結(jié)點(diǎn)時(shí)發(fā)現(xiàn)同步隊(duì)列中的前繼結(jié)點(diǎn)已取消,或者是更新前繼結(jié)點(diǎn)的狀態(tài)為 SIGNAL 失敗,這兩種情況都會(huì)立即喚醒線程,否則的話在 signal 方法結(jié)束時(shí)就不會(huì)去喚醒已在同步隊(duì)列中的線程,而是等到它的前繼結(jié)點(diǎn)來(lái)喚醒。當(dāng)然,線程阻塞在這里除了可以調(diào)用 signal 方法喚醒之外,線程還可以響應(yīng)中斷,如果線程在這里收到中斷請(qǐng)求就會(huì)繼續(xù)往下執(zhí)行。
可以看到線程醒來(lái)后會(huì)馬上檢查是否是由于中斷喚醒的還是通過(guò) signal 方法喚醒的,如果是因?yàn)橹袛鄦拘训耐瑯訒?huì)將這個(gè)結(jié)點(diǎn)轉(zhuǎn)移到同步隊(duì)列中去,只不過(guò)是通過(guò)調(diào)用 transferAfterCancelledWait 方法來(lái)實(shí)現(xiàn)的。最后執(zhí)行完這一步之后就會(huì)返回中斷情況并跳出 while 循環(huán)。
第四步:結(jié)點(diǎn)移出條件隊(duì)列后的操作
//線程醒來(lái)后就會(huì)以獨(dú)占模式獲取鎖
if(acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
//這步操作主要為防止線程在signal之前中斷而導(dǎo)致沒(méi)與條件隊(duì)列斷絕聯(lián)系
if(node.nextWaiter !=null) {
unlinkCancelledWaiters();
}
//根據(jù)中斷模式進(jìn)行響應(yīng)的中斷處理
if(interruptMode !=0) {
reportInterruptAfterWait(interruptMode);
}
//結(jié)束條件等待后根據(jù)中斷情況做出相應(yīng)處理
privatevoidreportInterruptAfterWait(intinterruptMode)throwsInterruptedException{
//如果中斷模式是THROW_IE就拋出異常
if(interruptMode == THROW_IE) {
thrownewInterruptedException();
//如果中斷模式是REINTERRUPT就自己掛起
}elseif(interruptMode == REINTERRUPT) {
selfInterrupt();
}
}
當(dāng)線程終止了 while 循環(huán)也就是條件等待后,就會(huì)回到同步隊(duì)列中。不管是因?yàn)檎{(diào)用 signal 方法回去的還是因?yàn)榫€程中斷導(dǎo)致的,結(jié)點(diǎn)最終都會(huì)在同步隊(duì)列中。這時(shí)就會(huì)調(diào)用 acquireQueued 方法執(zhí)行在同步隊(duì)列中獲取鎖的操作,這個(gè)方法我們?cè)讵?dú)占模式這一篇已經(jīng)詳細(xì)的講過(guò)。
也就是說(shuō),結(jié)點(diǎn)從條件隊(duì)列出來(lái)后又是乖乖的走獨(dú)占模式下獲取鎖的那一套,等這個(gè)結(jié)點(diǎn)再次獲得鎖之后,就會(huì)調(diào)用 reportInterruptAfterWait 方法來(lái)根據(jù)這期間的中斷情況做出相應(yīng)的響應(yīng)。如果中斷發(fā)生在 signal 方法之前,interruptMode 就為 THROW_IE,再次獲得鎖后就拋出異常;如果中斷發(fā)生在 signal 方法之后,interruptMode 就為 REINTERRUPT,再次獲得鎖后就重新中斷。
2. 不響應(yīng)線程中斷的條件等待
//不響應(yīng)線程中斷的條件等待
publicfinalvoidawaitUninterruptibly(){
//將當(dāng)前線程添加到條件隊(duì)列尾部
Node node = addConditionWaiter();
//完全釋放鎖并返回當(dāng)前同步狀態(tài)
intsavedState = fullyRelease(node);
booleaninterrupted =false;
//結(jié)點(diǎn)一直在while循環(huán)里進(jìn)行條件等待
while(!isOnSyncQueue(node)) {
//條件隊(duì)列中所有的線程都在這里被掛起
LockSupport.park(this);
//線程醒來(lái)發(fā)現(xiàn)中斷并不會(huì)馬上去響應(yīng)
if(Thread.interrupted()) {
interrupted =true;
}
}
if(acquireQueued(node, savedState) || interrupted) {
//在這里響應(yīng)所有中斷請(qǐng)求, 滿足以下兩個(gè)條件之一就會(huì)將自己掛起
//1.線程在條件等待時(shí)收到中斷請(qǐng)求
//2.線程在acquireQueued方法里收到中斷請(qǐng)求
selfInterrupt();
}
}
3. 設(shè)置相對(duì)時(shí)間的條件等待 (不進(jìn)行自旋)
//設(shè)置定時(shí)條件等待(相對(duì)時(shí)間), 不進(jìn)行自旋等待
publicfinallongawaitNanos(longnanosTimeout)throwsInterruptedException{
//如果線程被中斷則拋出異常
if(Thread.interrupted()) {
thrownewInterruptedException();
}
//將當(dāng)前線程添加到條件隊(duì)列尾部
Node node = addConditionWaiter();
//在進(jìn)入條件等待之前先完全釋放鎖
intsavedState = fullyRelease(node);
longlastTime = System.nanoTime();
intinterruptMode =0;
while(!isOnSyncQueue(node)) {
//判斷超時(shí)時(shí)間是否用完了
if(nanosTimeout <=0L) {
//如果已超時(shí)就需要執(zhí)行取消條件等待操作
transferAfterCancelledWait(node);
break;
}
//將當(dāng)前線程掛起一段時(shí)間, 線程在這期間可能被喚醒, 也可能自己醒來(lái)
LockSupport.parkNanos(this, nanosTimeout);
//線程醒來(lái)后先檢查中斷信息
if((interruptMode = checkInterruptWhileWaiting(node)) !=0) {
break;
}
longnow = System.nanoTime();
//超時(shí)時(shí)間每次減去條件等待的時(shí)間
nanosTimeout -= now - lastTime;
lastTime = now;
}
//線程醒來(lái)后就會(huì)以獨(dú)占模式獲取鎖
if(acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
//由于transferAfterCancelledWait方法沒(méi)有把nextWaiter置空, 所有這里要再清理一遍
if(node.nextWaiter !=null) {
unlinkCancelledWaiters();
}
//根據(jù)中斷模式進(jìn)行響應(yīng)的中斷處理
if(interruptMode !=0) {
reportInterruptAfterWait(interruptMode);
}
//返回剩余時(shí)間
returnnanosTimeout - (System.nanoTime() - lastTime);
}
4. 設(shè)置相對(duì)時(shí)間的條件等待 (進(jìn)行自旋)
//設(shè)置定時(shí)條件等待(相對(duì)時(shí)間), 進(jìn)行自旋等待
publicfinalbooleanawait(longtime, TimeUnit unit)throwsInterruptedException{
if(unit ==null) {thrownewNullPointerException(); }
//獲取超時(shí)時(shí)間的毫秒數(shù)
longnanosTimeout = unit.toNanos(time);
//如果線程被中斷則拋出異常
if(Thread.interrupted()) {thrownewInterruptedException(); }
//將當(dāng)前線程添加條件隊(duì)列尾部
Node node = addConditionWaiter();
//在進(jìn)入條件等待之前先完全釋放鎖
intsavedState = fullyRelease(node);
//獲取當(dāng)前時(shí)間的毫秒數(shù)
longlastTime = System.nanoTime();
booleantimedout =false;
intinterruptMode =0;
while(!isOnSyncQueue(node)) {
//如果超時(shí)就需要執(zhí)行取消條件等待操作
if(nanosTimeout <=0L) {
timedout = transferAfterCancelledWait(node);
break;
}
//如果超時(shí)時(shí)間大于自旋時(shí)間, 就將線程掛起一段時(shí)間
if(nanosTimeout >= spinForTimeoutThreshold) {
LockSupport.parkNanos(this, nanosTimeout);
}
//線程醒來(lái)后先檢查中斷信息
if((interruptMode = checkInterruptWhileWaiting(node)) !=0) {
break;
}
longnow = System.nanoTime();
//超時(shí)時(shí)間每次減去條件等待的時(shí)間
nanosTimeout -= now - lastTime;
lastTime = now;
}
//線程醒來(lái)后就會(huì)以獨(dú)占模式獲取鎖
if(acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
//由于transferAfterCancelledWait方法沒(méi)有把nextWaiter置空, 所有這里要再清理一遍
if(node.nextWaiter !=null) {
unlinkCancelledWaiters();
}
//根據(jù)中斷模式進(jìn)行響應(yīng)的中斷處理
if(interruptMode !=0) {
reportInterruptAfterWait(interruptMode);
}
//返回是否超時(shí)標(biāo)志
return!timedout;
}
5. 設(shè)置絕對(duì)時(shí)間的條件等待
//設(shè)置定時(shí)條件等待(絕對(duì)時(shí)間)
publicfinalbooleanawaitUntil(Date deadline)throwsInterruptedException{
if(deadline ==null) {thrownewNullPointerException(); }
//獲取絕對(duì)時(shí)間的毫秒數(shù)
longabstime = deadline.getTime();
//如果線程被中斷則拋出異常
if(Thread.interrupted()) {thrownewInterruptedException(); }
//將當(dāng)前線程添加到條件隊(duì)列尾部
Node node = addConditionWaiter();
//在進(jìn)入條件等待之前先完全釋放鎖
intsavedState = fullyRelease(node);
booleantimedout =false;
intinterruptMode =0;
while(!isOnSyncQueue(node)) {
//如果超時(shí)就需要執(zhí)行取消條件等待操作
if(System.currentTimeMillis() > abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
//將線程掛起一段時(shí)間, 期間線程可能被喚醒, 也可能到了點(diǎn)自己醒來(lái)
LockSupport.parkUntil(this, abstime);
//線程醒來(lái)后先檢查中斷信息
if((interruptMode = checkInterruptWhileWaiting(node)) !=0) {
break;
}
}
//線程醒來(lái)后就會(huì)以獨(dú)占模式獲取鎖
if(acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
//由于transferAfterCancelledWait方法沒(méi)有把nextWaiter置空, 所有這里要再清理一遍
if(node.nextWaiter !=null) {
unlinkCancelledWaiters();
}
//根據(jù)中斷模式進(jìn)行響應(yīng)的中斷處理
if(interruptMode !=0) {
reportInterruptAfterWait(interruptMode);
}
//返回是否超時(shí)標(biāo)志
return!timedout;
}
6. 喚醒條件隊(duì)列中的頭結(jié)點(diǎn)
//喚醒條件隊(duì)列中的下一個(gè)結(jié)點(diǎn)
publicfinalvoidsignal(){
//判斷當(dāng)前線程是否持有鎖
if(!isHeldExclusively()) {
thrownewIllegalMonitorStateException();
}
Node first = firstWaiter;
//如果條件隊(duì)列中有排隊(duì)者
if(first !=null) {
//喚醒條件隊(duì)列中的頭結(jié)點(diǎn)
doSignal(first);
}
}
//喚醒條件隊(duì)列中的頭結(jié)點(diǎn)
privatevoiddoSignal(Node first){
do{
//1.將firstWaiter引用向后移動(dòng)一位
if( (firstWaiter = first.nextWaiter) ==null) {
lastWaiter =null;
}
//2.將頭結(jié)點(diǎn)的后繼結(jié)點(diǎn)引用置空
first.nextWaiter =null;
//3.將頭結(jié)點(diǎn)轉(zhuǎn)移到同步隊(duì)列, 轉(zhuǎn)移完成后有可能喚醒線程
//4.如果transferForSignal操作失敗就去喚醒下一個(gè)結(jié)點(diǎn)
}while(!transferForSignal(first) && (first = firstWaiter) !=null);
}
//將指定結(jié)點(diǎn)從條件隊(duì)列轉(zhuǎn)移到同步隊(duì)列中
finalbooleantransferForSignal(Node node){
//將等待狀態(tài)從CONDITION設(shè)置為0
if(!compareAndSetWaitStatus(node, Node.CONDITION,0)) {
//如果更新?tīng)顟B(tài)的操作失敗就直接返回false
//可能是transferAfterCancelledWait方法先將狀態(tài)改變了, 導(dǎo)致這步CAS操作失敗
returnfalse;
}
//將該結(jié)點(diǎn)添加到同步隊(duì)列尾部
Node p = enq(node);
intws = p.waitStatus;
if(ws >0|| !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) {
//出現(xiàn)以下情況就會(huì)喚醒當(dāng)前線程
//1.前繼結(jié)點(diǎn)是取消狀態(tài)
//2.更新前繼結(jié)點(diǎn)的狀態(tài)為SIGNAL操作失敗
LockSupport.unpark(node.thread);
}
returntrue;
}
可以看到 signal 方法最終的核心就是去調(diào)用 transferForSignal 方法,在 transferForSignal 方法中首先會(huì)用 CAS 操作將結(jié)點(diǎn)的狀態(tài)從 CONDITION 設(shè)置為 0,然后再調(diào)用 enq 方法將該結(jié)點(diǎn)添加到同步隊(duì)列尾部。
我們?cè)倏吹浇酉聛?lái)的 if 判斷語(yǔ)句,這個(gè)判斷語(yǔ)句主要是用來(lái)判斷什么時(shí)候會(huì)去喚醒線程,出現(xiàn)這兩種情況就會(huì)立即喚醒線程,一種是當(dāng)發(fā)現(xiàn)前繼結(jié)點(diǎn)的狀態(tài)是取消狀態(tài)時(shí),還有一種是更新前繼結(jié)點(diǎn)的狀態(tài)失敗時(shí)。
這兩種情況都會(huì)馬上去喚醒線程,否則的話就僅僅只是將結(jié)點(diǎn)從條件隊(duì)列中轉(zhuǎn)移到同步隊(duì)列中就完了,而不會(huì)立馬去喚醒結(jié)點(diǎn)中的線程。signalAll 方法也大致類似,只不過(guò)它是去循環(huán)遍歷條件隊(duì)列中的所有結(jié)點(diǎn),并將它們轉(zhuǎn)移到同步隊(duì)列,轉(zhuǎn)移結(jié)點(diǎn)的方法也還是調(diào)用 transferForSignal 方法。
7. 喚醒條件隊(duì)列的所有結(jié)點(diǎn)
//喚醒條件隊(duì)列后面的全部結(jié)點(diǎn)
publicfinalvoidsignalAll(){
//判斷當(dāng)前線程是否持有鎖
if(!isHeldExclusively()) {
thrownewIllegalMonitorStateException();
}
//獲取條件隊(duì)列頭結(jié)點(diǎn)
Node first = firstWaiter;
if(first !=null) {
//喚醒條件隊(duì)列的所有結(jié)點(diǎn)
doSignalAll(first);
}
}
//喚醒條件隊(duì)列的所有結(jié)點(diǎn)
privatevoiddoSignalAll(Node first){
//先把頭結(jié)點(diǎn)和尾結(jié)點(diǎn)的引用置空
lastWaiter = firstWaiter =null;
do{
//先獲取后繼結(jié)點(diǎn)的引用
Node next = first.nextWaiter;
//把即將轉(zhuǎn)移的結(jié)點(diǎn)的后繼引用置空
first.nextWaiter =null;
//將結(jié)點(diǎn)從條件隊(duì)列轉(zhuǎn)移到同步隊(duì)列
transferForSignal(first);
//將引用指向下一個(gè)結(jié)點(diǎn)
first = next;
}while(first !=null);
}
至此,我們整個(gè)的 AbstractQueuedSynchronizer 源碼分析就結(jié)束了,相信通過(guò)這四篇的分析,大家能更好的掌握并理解 AQS。
這個(gè)類確實(shí)很重要,因?yàn)樗瞧渌芏嗤筋惖幕捎诠P者水平和表達(dá)能力有限,如果哪些地方?jīng)]有表述清楚的,或者理解不到位的,還請(qǐng)廣大讀者們能夠及時(shí)指正,共同探討學(xué)習(xí)。