AQS詳解:
AQS原理
AQS:AbstractQuenedSynchronizer抽象的隊(duì)列式同步器。是除了java自帶的synchronized關(guān)鍵字之外的鎖機(jī)制。
AQS的全稱為(AbstractQueuedSynchronizer),這個(gè)類在java.util.concurrent.locks包
AQS的核心思想是,如果被請(qǐng)求的共享資源空閑,則將當(dāng)前請(qǐng)求資源的線程設(shè)置為有效的工作線程,并將共享資源設(shè)置為鎖定狀態(tài),如果被請(qǐng)求的共享資源被占用,那么就需要一套線程阻塞等待以及被喚醒時(shí)鎖分配的機(jī)制,這個(gè)機(jī)制AQS是用CLH隊(duì)列鎖實(shí)現(xiàn)的,即將暫時(shí)獲取不到鎖的線程加入到隊(duì)列中。
CLH(Craig,Landin,and Hagersten)隊(duì)列是一個(gè)虛擬的雙向隊(duì)列,虛擬的雙向隊(duì)列即不存在隊(duì)列實(shí)例,僅存在節(jié)點(diǎn)之間的關(guān)聯(lián)關(guān)系。
AQS是將每一條請(qǐng)求共享資源的線程封裝成一個(gè)CLH鎖隊(duì)列的一個(gè)結(jié)點(diǎn)(Node),來實(shí)現(xiàn)鎖的分配。
用大白話來說,AQS就是基于CLH隊(duì)列,用volatile修飾共享變量state,線程通過CAS去改變狀態(tài)符,成功則獲取鎖成功,失敗則進(jìn)入等待隊(duì)列,等待被喚醒。
注意:AQS是自旋鎖:在等待喚醒的時(shí)候,經(jīng)常會(huì)使用自旋(while(!cas()))的方式,不停地嘗試獲取鎖,直到被其他線程獲取成功
實(shí)現(xiàn)了AQS的鎖有:自旋鎖、互斥鎖、讀鎖寫鎖、條件產(chǎn)量、信號(hào)量、柵欄都是AQS的衍生物
AQS 定義了兩種資源共享方式:
1.Exclusive:獨(dú)占,只有一個(gè)線程能執(zhí)行,如ReentrantLock
2.Share:共享,多個(gè)線程可以同時(shí)執(zhí)行,如Semaphore、CountDownLatch、ReadWriteLock,CyclicBarrier
AQS底層使用了模板方法模式
同步器的設(shè)計(jì)是基于模板方法模式的,如果需要自定義同步器一般的方式是這樣(模板方法模式很經(jīng)典的一個(gè)應(yīng)用):
使用者繼承AbstractQueuedSynchronizer并重寫指定的方法。(這些重寫方法很簡(jiǎn)單,無非是對(duì)于共享資源state的獲取和釋放)
將AQS組合在自定義同步組件的實(shí)現(xiàn)中,并調(diào)用其模板方法,而這些模板方法會(huì)調(diào)用使用者重寫的方法。
這和我們以往通過實(shí)現(xiàn)接口的方式有很大區(qū)別,這是模板方法模式很經(jīng)典的一個(gè)運(yùn)用。