04隊(duì)列同步器(Java并發(fā)編程的藝術(shù))

1.定義

隊(duì)列同步器AbstractQueuedSynchronizer,簡(jiǎn)稱AQS,是用來(lái)構(gòu)建鎖或者其他同步組件的基礎(chǔ)框架,是java.util.concurrent中基礎(chǔ)。AQS使用一個(gè)int成員變量表示同步狀態(tài),通過(guò)內(nèi)置的FIFO隊(duì)列來(lái)完成資源線程的排隊(duì)工作。

2.實(shí)現(xiàn)分析

2.1 同步隊(duì)列

AQS依賴內(nèi)部的同步隊(duì)列(FIFO雙向隊(duì)列)來(lái)完成同步狀態(tài)管理,當(dāng)前線程獲取同步狀態(tài)失敗時(shí),同步隊(duì)列會(huì)將當(dāng)前線程以及等待狀態(tài)信息構(gòu)成一個(gè)節(jié)點(diǎn)并加入到同步隊(duì)列,同步會(huì)阻塞當(dāng)前的線程,當(dāng)同步釋放的時(shí)候,會(huì)把首節(jié)點(diǎn)的線程喚醒,使其再次嘗試獲取同步狀態(tài)。

同步隊(duì)列中重要屬性及描述:

(1)int waitStatus 等待狀態(tài)

-CANCELLED,取消狀態(tài),值為1,由于同步隊(duì)列中等待的線程等待超時(shí)或者被中斷,需要從同步隊(duì)列中取消等待,節(jié)點(diǎn)進(jìn)入該狀態(tài)將不會(huì)變化

-SIGNAL,通知狀態(tài),值為-1,后繼節(jié)點(diǎn)的線程處于等待狀態(tài),而當(dāng)前節(jié)點(diǎn)的線程如果釋放了同步狀態(tài)或被取消,將會(huì)通知后繼節(jié)點(diǎn),使得后繼節(jié)點(diǎn)得以運(yùn)行

-CONDTION,條件阻塞狀態(tài),值為-2,節(jié)點(diǎn)在等待隊(duì)列中,節(jié)點(diǎn)線程等待在COndition上,當(dāng)其他線程對(duì)Condition調(diào)用了signal()方法后,該節(jié)點(diǎn)將會(huì)從等待隊(duì)列中轉(zhuǎn)移到同步隊(duì)列加入到對(duì)同步狀態(tài)的獲取中

-PROPAGATE,傳播狀態(tài),值為-3,表示下一次共享式同步狀態(tài)獲取將會(huì)無(wú)條件地傳播下去

-INITIAL,值為0,初始狀態(tài)

節(jié)點(diǎn)是構(gòu)成同步隊(duì)列的基礎(chǔ),同步器擁有首節(jié)點(diǎn)、尾節(jié)點(diǎn),沒(méi)有成功獲取同步狀態(tài)的線程會(huì)加入到該隊(duì)列的尾部,同步隊(duì)列的基本結(jié)構(gòu)如下所示:

同步隊(duì)列基本結(jié)構(gòu)

同步隊(duì)列包括了兩個(gè)節(jié)點(diǎn)的引用,一個(gè)指向頭結(jié)點(diǎn),一個(gè)指向尾節(jié)點(diǎn)。獨(dú)占模式下,當(dāng)一個(gè)線程成功獲取同步狀態(tài),其他線程將無(wú)法獲取同步狀態(tài),將會(huì)被構(gòu)造成節(jié)點(diǎn)加入到同步隊(duì)列的尾部,加入的過(guò)程使用CAS,保證線程安全。

節(jié)點(diǎn)加入同步隊(duì)列

同步隊(duì)列遵循FIFO,首節(jié)點(diǎn)是獲取同步狀態(tài)成功的節(jié)點(diǎn),首節(jié)點(diǎn)的線程在釋放同步狀態(tài)時(shí),會(huì)喚醒后繼節(jié)點(diǎn),而后繼節(jié)點(diǎn)將會(huì)在獲取同步狀態(tài)成功時(shí)將自己設(shè)置成首節(jié)點(diǎn)。

首節(jié)點(diǎn)設(shè)置

2.2 獨(dú)占式同步狀態(tài)的獲取和釋放

通過(guò)調(diào)用同步器的acquire(int args)方法可以獲取同步狀態(tài),該方法對(duì)中斷不敏感。

首先調(diào)用自定義同步器實(shí)現(xiàn)的tryAcquire(int args)方法,該方法保證線程安全的獲取同步狀態(tài),如果獲取失敗,則構(gòu)造同步節(jié)點(diǎn)(獨(dú)占式節(jié)點(diǎn),EXCLUSIVE,同一時(shí)刻只能有一個(gè)線程成功獲取同步狀態(tài))并通過(guò)addWaiter(Node node)方法將該節(jié)點(diǎn)加入到同步隊(duì)列的尾部,最后調(diào)用acquireQueued(Node node, int args)方法,使得該節(jié)點(diǎn)以“死循環(huán)”的方式獲取同步狀態(tài)。如果獲取不到則阻塞節(jié)點(diǎn)中的線程,而被阻塞線程的喚醒主要依賴前驅(qū)節(jié)點(diǎn)的出隊(duì)或阻塞線程被中斷來(lái)實(shí)現(xiàn)。

上述的代碼中,主要通過(guò)compareAndSetTail(Node expect, Node update)方法保證節(jié)點(diǎn)能夠被線程安全添加到尾節(jié)點(diǎn)。enq(final Node node)方法中,同步器通過(guò)“死循環(huán)”的方式保證節(jié)點(diǎn)能夠添加到尾節(jié)點(diǎn)。

acquireQueued(final Node node, int arg)方法中,當(dāng)前線程在“死循環(huán)”中獲取嘗試獲取同步狀態(tài),但是只有頭節(jié)點(diǎn)才能嘗試獲取同步狀態(tài)。


獨(dú)占式同步狀態(tài)獲取流程

release(int arg)方法執(zhí)行時(shí),會(huì)喚醒頭節(jié)點(diǎn)的后續(xù)節(jié)點(diǎn)線程,unparkSuccessor(Node node)方法使用LockSupport來(lái)喚醒處于等待的狀態(tài)的線程。

2.3 共享式同步狀態(tài)的獲取和釋放

共享式獲取與獨(dú)占式獲取最主要的區(qū)別是在于同一時(shí)刻能否有多個(gè)線程同時(shí)獲取到同步狀態(tài)。cquireShared(int arg)方法可以以共享式地獲取同步狀態(tài)。


在acquireShared(int arg)方法中,同步器調(diào)用tryAcquireShared(int arg)方法嘗試獲取同步狀態(tài),其返回值大于等于0時(shí),表示獲取同步狀態(tài)成功;否則,反之。在doAcquireShared(int arg)方法中,如果當(dāng)前節(jié)點(diǎn)的前驅(qū)為頭節(jié)點(diǎn),嘗試獲取同步狀態(tài),如果返回值大于等于0,表示該線程獲取到同步狀態(tài)成功并退出自旋。釋放同步狀態(tài)與獨(dú)占式類似,releaseShared(int arg)方法在釋放同步狀態(tài)之后,將會(huì)喚醒后續(xù)處于等待狀態(tài)的節(jié)點(diǎn)。

2.4 獨(dú)占式超時(shí)獲取同步狀態(tài)

通過(guò)調(diào)用同步器的doAcquireNanos(int arg, long nanosTimeout)方法可以支持超時(shí)獲取同步狀態(tài),即在指定的時(shí)間段內(nèi)獲取同步狀態(tài),如果獲取到同步狀態(tài)則返回true,否則,返回false。該方法還支持響應(yīng)中斷。

該方法在自旋的過(guò)程中,當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)為頭節(jié)點(diǎn)時(shí)嘗試獲取同步狀態(tài),如果獲取成功,則直接返回,這個(gè)過(guò)程和獨(dú)占式同步獲取過(guò)程類似,但是獲取失敗的處理流程不同。如果獲取失敗,則判斷當(dāng)前時(shí)間是否超過(guò)該接口設(shè)置的超時(shí)時(shí)間,若沒(méi)有超時(shí),且超時(shí)時(shí)間大于1000ns,則重新計(jì)算超時(shí)間隔nanosTimeout,然后使當(dāng)前線程等待nanosTimeout納秒。另外需要判斷當(dāng)前線程狀態(tài)是否是中斷狀態(tài),若是,直接拋出中斷異常,否則繼續(xù)自旋。


獨(dú)占式超時(shí)獲取同步狀態(tài)流程
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容