前言
隊(duì)列同步器 AbstractQueuedSynchronizer(以下簡稱 AQS),是用來構(gòu)建鎖或者其他同步組件的基礎(chǔ)框架。它使用一個(gè) int 成員變量來表示同步狀態(tài),通過 CAS 操作對同步狀態(tài)進(jìn)行修改,確保狀態(tài)的改變是安全的。通過內(nèi)置的 FIFO (First In First Out)隊(duì)列來完成資源獲取線程的排隊(duì)工作。更多關(guān)于 Java 多線程的文章可以轉(zhuǎn)到 這里
AQS 和 synchronized
在介紹 AQS 的使用之前,需要首先說明一點(diǎn),AQS 同步和 synchronized 關(guān)鍵字同步(以下簡稱 synchronized 同步)是采用的兩種不同的機(jī)制。首先看下 synchronized 同步,synchronized 關(guān)鍵字經(jīng)過編譯之后,會(huì)在同步塊的前后分別形成 monitorenter 和 monitorexit 這兩個(gè)字節(jié)碼指令,這兩個(gè)字節(jié)碼需要關(guān)聯(lián)到一個(gè)監(jiān)視對象,當(dāng)線程執(zhí)行 monitorenter 指令時(shí),需要首先獲得獲得監(jiān)視對象的鎖,這里監(jiān)視對象鎖就是進(jìn)入同步塊的憑證,只有獲得了憑證才可以進(jìn)入同步塊,當(dāng)線程離開同步塊時(shí),會(huì)執(zhí)行 monitorexit 指令,釋放對象鎖。
在 AQS 同步中,使用一個(gè) int 類型的變量 state 來表示當(dāng)前同步塊的狀態(tài)。以獨(dú)占式同步(一次只能有一個(gè)線程進(jìn)入同步塊)為例,state 的有效值有兩個(gè) 0 和 1,其中 0 表示當(dāng)前同步塊中沒有線程,1 表示同步塊中已經(jīng)有線程在執(zhí)行。當(dāng)線程要進(jìn)入同步塊時(shí),需要首先判斷 state 的值是否為 0,假設(shè)為 0,會(huì)嘗試將 state 修改為 1,只有修改成功了之后,線程才可以進(jìn)入同步塊。注意上面提到的兩個(gè)條件:
state 為 0,證明當(dāng)前同步塊中沒有線程在執(zhí)行,所以當(dāng)前線程可以嘗試獲得進(jìn)入同步塊的憑證,而這里的憑證就是是否成功將 state 修改為 1(在 synchronized 同步中,我們說的憑證是對象鎖,但是對象