AQS 原理剖析

AQS即AbstractQueuedSynchronizer類稱作隊(duì)列同步器,是構(gòu)建其他同步器的一個(gè)重要的基礎(chǔ)框架,同步器自身是沒有實(shí)現(xiàn)任何同步接口。它是通過控制一個(gè)int類型的state變量來表示同步狀態(tài),使用一個(gè)內(nèi)置的FIFO(先進(jìn)先出)隊(duì)列來構(gòu)建工作隊(duì)列操作。
同步器定義有兩種資源共享方式:Exclusive(獨(dú)占式)和Share(共享式)的獲取同步狀態(tài)。
獨(dú)占式:一個(gè)時(shí)間點(diǎn)只能執(zhí)行一個(gè)線程。共享式:一個(gè)時(shí)間點(diǎn)可多個(gè)線程同時(shí)執(zhí)行。
使用方式
同步器的設(shè)計(jì)采用模板模式,要實(shí)現(xiàn)一個(gè)同步組件得先繼承AbstractQueuedSynchronizer類,通過調(diào)用同步器提供的方法和重寫同步器的方法來實(shí)現(xiàn)。
調(diào)用同步器中的方法就是調(diào)用前面提到的通過state變量值的操作來表示同步操作,state是被volatile修飾來保證線程可見性。
| 方法名 | 描述 |
|---|---|
| getState() | 獲取當(dāng)前線程同步狀態(tài)值。 |
| setState(int newState) | 設(shè)置當(dāng)前同步狀態(tài)值。 |
| compareAndSetState(int expect, int update) | 通過CAS設(shè)置state的值。 |
為了避免被重寫,以上方法都被final修飾了。
實(shí)現(xiàn)同步組件,需要自己根據(jù)自己定制化的需求進(jìn)行處理,所以需要自己重寫同步器提供的方法,要重寫的方法主要是獨(dú)占式獲取與釋放同步狀態(tài)、共享式獲取與釋放同步狀態(tài)。
tryAcquire(int arg) 獨(dú)占式獲取同步狀態(tài),返回值為boolean類型,獲取成返回true,獲取失敗返回false。
tryRelease(int arg) 獨(dú)占式釋放同步狀態(tài),返回值為boolean類型,釋放成返回true,釋放失敗返回false。
tryAcquireShared(int arg) 共享式獲取同步狀態(tài),返回值為int類型,獲取成功返回大于 0 的值。
tryReleaseShared(int arg) 共享式釋放同步狀態(tài),返回值為boolean類型,釋放成返回true,釋放失敗返回false。
isHeldExclusively() 獨(dú)占模式下是否被當(dāng)前前程獨(dú)占,返回值為boolean類型,已被當(dāng)前線程所獨(dú)占返回true,反之為false。
同步器隊(duì)列
一個(gè)同步器里面擁有一個(gè)同步隊(duì)列和多個(gè)等待隊(duì)列。
同步隊(duì)列
在AbstractQueuedSynchronizer類中,有一個(gè)內(nèi)部類Node,通過該類構(gòu)造一個(gè)內(nèi)部的同步隊(duì)列,這是一個(gè)FIFO 雙向隊(duì)列。當(dāng)前運(yùn)行線程回去同步狀態(tài)時(shí),如果獲取失敗,則將當(dāng)前線程信息創(chuàng)建一個(gè)Node追加到同步隊(duì)列尾部,然后阻塞當(dāng)前線程,直到隊(duì)列的上一個(gè)節(jié)點(diǎn)的同步狀態(tài)釋放,再喚醒當(dāng)前線程嘗試重新獲取同步狀態(tài)。這個(gè)重新獲取同步狀態(tài)操作的節(jié)點(diǎn),一定要是同步隊(duì)列中第一節(jié)點(diǎn)。
Node 源碼如下:
static?final?class?Node?{
????//?共享模式下等待的標(biāo)記
????static?final?Node?SHARED?=?new?Node();
????//?獨(dú)占模式下等待的標(biāo)記
????static?final?Node?EXCLUSIVE?=?null;
????/*
????*?等待狀態(tài)常量值,以下四個(gè)常量都是
????*/
????static?final?int?CANCELLED?=??1;
????
????static?final?int?SIGNAL????=?-1;
????
????static?final?int?CONDITION?=?-2;
????
????static?final?int?PROPAGATE?=?-3;
????//?等待狀態(tài)
????volatile?int?waitStatus;
????//?當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)
????volatile?Node?prev;
????//?當(dāng)前節(jié)點(diǎn)的后繼節(jié)點(diǎn)
????volatile?Node?next;
????//?獲取同步狀態(tài)的線程(引用)
????volatile?Thread?thread;
????//?等待隊(duì)列中的后繼節(jié)點(diǎn)
????Node?nextWaiter;
????//?是否共享模式
????final?boolean?isShared()?{
????????return?nextWaiter?==?SHARED;
????}
????//?獲取前驅(qū)節(jié)點(diǎn)
????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;
????}
}
通過以上代碼,可以看到節(jié)點(diǎn)中保存了節(jié)點(diǎn)模式、等待狀態(tài)、線程引用、前驅(qū)和后繼節(jié)點(diǎn),構(gòu)造節(jié)點(diǎn)。
同步隊(duì)列中被阻塞的線程的等待狀態(tài)包含有四個(gè)常量值:CANCELLED、SIGNAL、CONDITION、PROPAGATE ,它們對(duì)應(yīng)的被阻塞原因如下:
CANCELLED同步隊(duì)列中當(dāng)前節(jié)點(diǎn)的線程等待超時(shí)或被中斷,需要從同步隊(duì)列中取消等待。SIGNAL當(dāng)前節(jié)點(diǎn)釋放同步狀態(tài)或被取消后,通知后繼節(jié)點(diǎn)的線程運(yùn)行。CONDITION當(dāng)前節(jié)點(diǎn)在 Condition 上等待,當(dāng)其他線程對(duì) Condition 調(diào)用了 signal() 方法后,該節(jié)點(diǎn)將添加到同步隊(duì)列中。PROPAGATE該狀態(tài)存在共享模式的首節(jié)點(diǎn)中,當(dāng)前節(jié)點(diǎn)喚醒后將傳播喚醒其他節(jié)點(diǎn)。
同步器中持有同步隊(duì)列的首節(jié)點(diǎn)和尾節(jié)點(diǎn)的引用,在AbstractQueuedSynchronizer中分別對(duì)應(yīng)head和tail字段。

所以同步隊(duì)列的基本結(jié)構(gòu)如圖:
等待隊(duì)列AbstractQueuedSynchronizer類中包含一個(gè)內(nèi)部類ConditionObject,該類實(shí)現(xiàn)了Condition的接口。一個(gè)Condition對(duì)象包含一個(gè)等待隊(duì)列,同時(shí)Condition對(duì)象可以實(shí)現(xiàn)等待/通知功能。
Condition持有等待隊(duì)列中的首節(jié)點(diǎn)(firstWaiter)和尾節(jié)點(diǎn)(lastWaiter),如下圖代碼所示:

如果當(dāng)前線程調(diào)用Condition.await()時(shí),會(huì)將當(dāng)前線程信息構(gòu)建一個(gè) Node 節(jié)點(diǎn),因?yàn)?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">Condition持有等待隊(duì)列中的首尾節(jié)點(diǎn),所以將當(dāng)前等待隊(duì)列中的尾節(jié)點(diǎn)的nextWaiter指向當(dāng)前線程構(gòu)建的節(jié)點(diǎn),同時(shí)更新lastWaiter的引用節(jié)點(diǎn)。
上述過程中的節(jié)點(diǎn)、隊(duì)列的操作,是獲取到鎖的線程來調(diào)用Condition.await()的,所以整個(gè)執(zhí)行過程在沒有基于 CAS 的情況下,也是線程安全的。
通過以上的描述,可以知道一個(gè)同步器中同步隊(duì)列、等待隊(duì)列構(gòu)成的示意圖:

當(dāng)調(diào)用Condition.await()時(shí),同步隊(duì)列中的首節(jié)點(diǎn),也就是當(dāng)前線程所創(chuàng)建的節(jié)點(diǎn),會(huì)加入到等待隊(duì)列中的尾部,釋放當(dāng)前線程的同步狀態(tài)并且喚醒同步隊(duì)列的后繼節(jié)點(diǎn),當(dāng)前線程也就進(jìn)入等待狀態(tài),這個(gè)先后順序不能顛倒。這個(gè)過程相當(dāng)于同步隊(duì)列的首節(jié)點(diǎn)的線程構(gòu)造新的節(jié)點(diǎn)加入到等待隊(duì)列的尾部。

當(dāng)調(diào)用Condition.signal()方法時(shí),會(huì)先將等待隊(duì)列中首節(jié)點(diǎn)轉(zhuǎn)移到同步隊(duì)列尾部,然后喚醒該同步隊(duì)列中的線程,該線程從Condition.await()中自旋退出,接著在在同步器的acquireQueued()中自旋獲取同步狀態(tài)。

當(dāng)調(diào)用Condition.wait()方法,同步隊(duì)列首節(jié)點(diǎn)轉(zhuǎn)移到等待隊(duì)列方法:
public?final?void?await()?throws?InterruptedException?{
????//?如果線程已中斷,則拋出中斷異常
????if?(Thread.interrupted())
????????throw?new?InterruptedException();
????//?添加節(jié)點(diǎn)到等待隊(duì)列中
????Node?node?=?addConditionWaiter();
????//?修改?state?來達(dá)到釋放同步狀態(tài),避免死鎖
????int?savedState?=?fullyRelease(node);
????
????int?interruptMode?=?0;
????//?判斷當(dāng)前節(jié)點(diǎn)是否在同步隊(duì)列中
????while?(!isOnSyncQueue(node))?{
????????LockSupport.park(this);
????????if?((interruptMode?=?checkInterruptWhileWaiting(node))?!=?0)
????????????break;
????}
????//?繼續(xù)獲取同步狀態(tài)競(jìng)爭
????if?(acquireQueued(node,?savedState)?&&?interruptMode?!=?THROW_IE)
????????interruptMode?=?REINTERRUPT;
????if?(node.nextWaiter?!=?null)?//?清除已取消的節(jié)點(diǎn)
????????unlinkCancelledWaiters();
????if?(interruptMode?!=?0)?//?被中斷時(shí)的處理
????????reportInterruptAfterWait(interruptMode);
}
上面addc方法是向等待隊(duì)列中添加一個(gè)新的節(jié)點(diǎn)。
private?Node?addConditionWaiter()?{
????//?獲取等待隊(duì)列中尾節(jié)點(diǎn)
????Node?t?=?lastWaiter;
????//?如果最后一個(gè)節(jié)點(diǎn)已取消,則清除取消節(jié)點(diǎn)
????if?(t?!=?null?&&?t.waitStatus?!=?Node.CONDITION)?{
????????unlinkCancelledWaiters();
????????t?=?lastWaiter;
????}
????//?利用當(dāng)前線程信息創(chuàng)建等待隊(duì)列的節(jié)點(diǎn)
????Node?node?=?new?Node(Thread.currentThread(),?Node.CONDITION);
????
????if?(t?==?null)?//?如果最后尾節(jié)點(diǎn)為空,當(dāng)前節(jié)點(diǎn)則為等待隊(duì)列的首節(jié)點(diǎn)
????????firstWaiter?=?node;
????else?//?否則將當(dāng)前尾節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指向當(dāng)前線程信息所構(gòu)造的節(jié)點(diǎn)
????????t.nextWaiter?=?node;
????lastWaiter?=?node;??//?更新?Condition?的尾節(jié)點(diǎn)引用
????return?node;
}
當(dāng)調(diào)用Condition.signal()方法,等待隊(duì)列首節(jié)點(diǎn)轉(zhuǎn)移到同步隊(duì)列方法:
public?final?void?signal()?{
????//?是否被當(dāng)前線程所獨(dú)占
????if?(!isHeldExclusively())
????????throw?new?IllegalMonitorStateException();
????//?獲取等待隊(duì)列中首節(jié)點(diǎn)
????Node?first?=?firstWaiter;
????if?(first?!=?null)
????????//?轉(zhuǎn)移到同步隊(duì)列,然后喚醒該節(jié)點(diǎn)
????????doSignal(first);
}
轉(zhuǎn)移同步隊(duì)列首節(jié)點(diǎn)到同步隊(duì)列,并喚醒該節(jié)點(diǎn)方法doSignal()
private?void?doSignal(Node?first)?{
????do?{
??????if?(?(firstWaiter?=?first.nextWaiter)?==?null)
??????????lastWaiter?=?null;
??????????//?去除首節(jié)點(diǎn)
??????????first.nextWaiter?=?null;
????}?while?(!transferForSignal(first)?&&?//?從等待隊(duì)列中轉(zhuǎn)移到同步隊(duì)列
??????????????(first?=?firstWaiter)?!=?null);
}
轉(zhuǎn)移等待隊(duì)列到同步隊(duì)列方法transferForSignal(Node node)
final?boolean?transferForSignal(Node?node)?{
????//?驗(yàn)證節(jié)點(diǎn)是否被取消
????if?(!compareAndSetWaitStatus(node,?Node.CONDITION,?0))
????????return?false;
????//?轉(zhuǎn)移節(jié)點(diǎn)至同步隊(duì)列
????Node?p?=?enq(node);
????int?ws?=?p.waitStatus;
????if?(ws?>?0?||?!compareAndSetWaitStatus(p,?ws,?Node.SIGNAL))
????????LockSupport.unpark(node.thread);
????return?true;
}
等待隊(duì)列中的頭結(jié)點(diǎn)線程安全移動(dòng)到同步隊(duì)列方法enq(final Node node)
private?Node?enq(final?Node?node)?{
????for?(;;)?{
????????Node?t?=?tail;
????????//?同步隊(duì)列中如果為空,則初始化同步器
????????if?(t?==?null)?{?
????????????if?(compareAndSetHead(new?Node()))
????????????????tail?=?head;
????????}?else?{
????????????//?否則新節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)為當(dāng)前同步隊(duì)列的尾節(jié)點(diǎn)
????????????node.prev?=?t;
????????????//?設(shè)置當(dāng)前新節(jié)點(diǎn)為同步隊(duì)列的尾節(jié)點(diǎn),并更新先前同步隊(duì)列的尾節(jié)點(diǎn)的后繼節(jié)點(diǎn)指向當(dāng)前新節(jié)點(diǎn)
????????????if?(compareAndSetTail(t,?node))?{
????????????????t.next?=?node;
????????????????return?t;
????????????}
????????}
????}
}
獨(dú)占式同步狀態(tài)
獨(dú)占式同步狀態(tài)獲取和釋放是線程安全的操作,一個(gè)時(shí)間點(diǎn)確保只有一個(gè)線程獲取到同步狀態(tài)。
獨(dú)占式同步狀態(tài)獲取
acquire(int arg)方法是獲取獨(dú)占式同步狀態(tài)的方法,當(dāng)線程獲取同步失敗時(shí),會(huì)加入到同步隊(duì)列中。
public?final?void?acquire(int?arg)?{
????if?(!tryAcquire(arg)?&&
????????acquireQueued(addWaiter(Node.EXCLUSIVE),?arg))
????????selfInterrupt();
}
上述代碼中,當(dāng)執(zhí)行tryAcquire(int arg)方法獲取同步狀態(tài)失敗時(shí),接著通過addWaiter(Node.EXCLUSIVE)構(gòu)造當(dāng)前線程信息的節(jié)點(diǎn),隨后將新構(gòu)造的節(jié)點(diǎn)通過acquireQueued(final Node node, int arg)方法加入到同步隊(duì)列中,節(jié)點(diǎn)在同步隊(duì)列中自旋等待獲取同步狀態(tài)。
tryAcquire(int arg)是自定義同步器實(shí)現(xiàn)的,實(shí)現(xiàn)該方法需要保證線程安全獲取同步狀態(tài),前面講到AQS提供的compareAndSetState(int expect, int update)方法通過CAS設(shè)置state值來保證線程安全。
上面獲取獨(dú)占式同步狀態(tài)時(shí),主要分析acquireQueued(final Node node, int arg)方法,節(jié)點(diǎn)加入隊(duì)列并自旋等待。
final?boolean?acquireQueued(final?Node?node,?int?arg)?{
????boolean?failed?=?true;
????try?{
????????//?是否中斷標(biāo)識(shí)
????????boolean?interrupted?=?false;
????????for?(;;)?{
????????????//?獲取當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)
????????????final?Node?p?=?node.predecessor();
????????????//?如果前驅(qū)節(jié)點(diǎn)是首節(jié)點(diǎn),并且當(dāng)前節(jié)點(diǎn)獲取到同步狀態(tài)
????????????if?(p?==?head?&&?tryAcquire(arg))?{
????????????????//?將當(dāng)前節(jié)點(diǎn)設(shè)置為首節(jié)點(diǎn)
????????????????setHead(node);
????????????????//?將原首節(jié)點(diǎn)(即當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn))引用清空,利于 GC 回收
????????????????p.next?=?null;
????????????????//?成功獲取到同步狀態(tài)標(biāo)志
????????????????failed?=?false;
????????????????return?interrupted;
????????????}
????????????//?判斷前驅(qū)節(jié)點(diǎn)是否超時(shí)或取消,以及當(dāng)前線程是否被中斷
????????????if?(shouldParkAfterFailedAcquire(p,?node)?&&
????????????????parkAndCheckInterrupt())
????????????????interrupted?=?true;
????????}
????}?finally?{
????????//?如果被中斷,則節(jié)點(diǎn)出隊(duì)
????????if?(failed)
????????????cancelAcquire(node);
????}
}
在首節(jié)點(diǎn)釋放同步狀態(tài)后,同時(shí)喚醒后繼節(jié)點(diǎn)。后繼節(jié)點(diǎn)通過自旋的方式(這里利用死循環(huán)方式)也會(huì)檢查自己的前驅(qū)節(jié)點(diǎn)是否為首節(jié)點(diǎn),如果是前驅(qū)節(jié)點(diǎn)則會(huì)嘗試獲取同步狀態(tài)。獲取成功則返回,否則判斷是否被中斷或者繼續(xù)自旋上述獲取同步狀態(tài)操作。
獨(dú)占式同步狀態(tài)釋放
release(int arg)方法是釋放同步狀態(tài),當(dāng)釋放同步狀態(tài)后會(huì)喚醒后繼節(jié)點(diǎn)。
public?final?boolean?release(int?arg)?{
????if?(tryRelease(arg))?{
????????Node?h?=?head;
????????if?(h?!=?null?&&?h.waitStatus?!=?0)
????????????unparkSuccessor(h);
????????return?true;
????}
????return?false;
}
tryRelease(int arg)方法同樣也是自定義同步器實(shí)現(xiàn)。當(dāng)首節(jié)點(diǎn)不為空且處于等待狀態(tài)時(shí),那么調(diào)用unparkSuccessor(Node node)方法喚醒后繼節(jié)點(diǎn)。
private?void?unparkSuccessor(Node?node)?{
????//?CAS?設(shè)置等待狀態(tài)為初始狀態(tài)
????int?ws?=?node.waitStatus;
????if?(ws?0)
????????compareAndSetWaitStatus(node,?ws,?0);
????Node?s?=?node.next;
????//?如果當(dāng)前釋放同步狀態(tài)的節(jié)點(diǎn)不存在后繼節(jié)點(diǎn)或后繼節(jié)點(diǎn)超時(shí)/被中斷
????if?(s?==?null?||?s.waitStatus?>?0)?{
????????s?=?null;
????????//?從尾節(jié)點(diǎn)中開始尋找等待狀態(tài)的節(jié)點(diǎn)作為新首節(jié)點(diǎn),這里已排除當(dāng)前節(jié)點(diǎn)(t != node)
????????for?(Node?t?=?tail;?t?!=?null?&&?t?!=?node;?t?=?t.prev)
????????????if?(t.waitStatus?<=?0)
????????????????s?=?t;
????}
????if?(s?!=?null)
????????LockSupport.unpark(s.thread);
}
釋放同步狀態(tài)的整個(gè)過程就是:釋放同步狀態(tài),喚醒后繼節(jié)點(diǎn)。這個(gè)后繼節(jié)點(diǎn)必須滿足,非空、非當(dāng)前節(jié)點(diǎn)、等待狀態(tài)小于或等于 0 ,即SIGNAL、CONDITION、PROPAGATE和初始化狀態(tài)。
獨(dú)占式資源共享方式除了上面的同步狀態(tài)獲取,還有獨(dú)占式超時(shí)獲取使用的方法是doAcquireNanos(int arg, long nanosTimeout)、獨(dú)占式可中斷獲取使用的方法是acquireInterruptibly(int arg)。
共享式同步狀態(tài)
共享式同步狀態(tài)同一時(shí)間點(diǎn)可以有多個(gè)線程獲取到同步狀態(tài)。
共享式同步狀態(tài)獲取
acquireShared(int arg)方法是共享式同步狀態(tài)獲取的方法。
public?final?void?acquireShared(int?arg)?{
????if?(tryAcquireShared(arg)?0)
????????//?獲取同步狀態(tài)失敗后調(diào)用的方法
????????doAcquireShared(arg);
}
tryAcquireShared(int arg)方法是自定義同步器實(shí)現(xiàn)的,返回大于或等于 0 時(shí),表示獲取成功。如果小于 0 時(shí),獲取同步狀態(tài)失敗后會(huì)調(diào)用doAcquireShared(int arg)方法進(jìn)行再次嘗試獲取。
private?void?doAcquireShared(int?arg)?{、
????//?構(gòu)造一個(gè)當(dāng)前線程信息的新節(jié)點(diǎn)
????final?Node?node?=?addWaiter(Node.SHARED);
????boolean?failed?=?true;
????try?{
????????boolean?interrupted?=?false;
????????//?自旋式獲取同步狀態(tài)
????????for?(;;)?{
????????????final?Node?p?=?node.predecessor();
????????????//?判斷新節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)是否為首節(jié)點(diǎn)
????????????if?(p?==?head)?{
????????????????//?再次嘗試獲取同步狀態(tài)
????????????????int?r?=?tryAcquireShared(arg);
????????????????//?獲取成功后退出自旋
????????????????if?(r?>=?0)?{
????????????????????setHeadAndPropagate(node,?r);
????????????????????p.next?=?null;?//?help?GC
????????????????????if?(interrupted)
????????????????????????selfInterrupt();
????????????????????failed?=?false;
????????????????????return;
????????????????}
????????????}
????????????if?(shouldParkAfterFailedAcquire(p,?node)?&&
????????????????parkAndCheckInterrupt())
????????????????interrupted?=?true;
????????}
????}?finally?{
????????if?(failed)
????????????cancelAcquire(node);
????}
}
上面代碼中,當(dāng)獲取同步狀態(tài)失敗后,則創(chuàng)建一個(gè)共享模式類型的節(jié)點(diǎn),然后自旋式獲取同步狀態(tài),如果前驅(qū)節(jié)點(diǎn)為首節(jié)點(diǎn)時(shí)則嘗試再次獲取同步狀態(tài),獲取同步狀態(tài)成功后退出當(dāng)前自旋。
共享式釋放同步狀態(tài)
releaseShared(int arg)方法來釋放共享式同步狀態(tài)。
public?final?boolean?releaseShared(int?arg)?{
????if?(tryReleaseShared(arg))?{
????????//?同步狀態(tài)釋放成功后,喚醒后面等待狀態(tài)的節(jié)點(diǎn)
????????doReleaseShared();
????????return?true;
????}
????return?false;
}
上面tryReleaseShared(int arg)釋放同步狀態(tài)方法必須保證線程安全,因?yàn)樗鄠€(gè)線程獲取到同步狀態(tài)時(shí)會(huì)引發(fā)并發(fā)操作,可以通過循環(huán)操作和 CAS 來確保安前行。
doReleaseShared()方法喚醒后續(xù)等待狀態(tài)的節(jié)點(diǎn)。
private?void?doReleaseShared()?{
????for?(;;)?{
????????Node?h?=?head;
????????if?(h?!=?null?&&?h?!=?tail)?{
????????????int?ws?=?h.waitStatus;
????????????//?驗(yàn)證后繼節(jié)點(diǎn)的線程處于等待狀態(tài)
????????????if?(ws?==?Node.SIGNAL)?{
????????????????//?再次檢查后繼節(jié)點(diǎn)的線程是否處于等待狀態(tài)
????????????????if?(!compareAndSetWaitStatus(h,?Node.SIGNAL,?0))
????????????????????continue;???
????????????????//?喚醒后繼節(jié)點(diǎn),這時(shí)每喚醒一次就更新一次首節(jié)點(diǎn)
????????????????unparkSuccessor(h);
????????????}
????????????else?if?(ws?==?0?&&
??????????????????????!compareAndSetWaitStatus(h,?0,?Node.PROPAGATE))
????????????????continue;????????????????//?loop?on?failed?CAS
????????}
????????if?(h?==?head)???????????????????//?loop?if?head?changed
????????????break;
????}
}
共享同步狀態(tài)釋放后,自旋式依次喚醒隊(duì)列中節(jié)點(diǎn)。
總結(jié)
從 AQS 中可以借鑒它利用循環(huán)和 CAS 來確保并發(fā)的安全性的思路,同時(shí)它采用模板設(shè)計(jì)模式定義一個(gè)處理邏輯,將具體的特定處理邏輯交由子類自定義實(shí)現(xiàn)。在 ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch 以及 Tomncat 的 LimitLatch 都有用其作為同步器。

