其實一開始是想接著寫java鎖的,不過后面發現內置鎖和其他同步器基本都離不開AQS。既然AQS繞不過去,那只好就開始探究一下AQS了,AQS即AbstractQueuedSynchronizer,其支持的操作簡單的說包括:阻塞和非阻塞的同步;可選的超時;通過中斷實現取消以及定義了Condition接口。為了實現這些功能,我們需要對同步狀態進行原子管理,線程阻塞和釋放,隊列的管理。下面會進行簡單的說明。
- 狀態管理
用一個volatile的int表示狀態,提供getState,setState以及CompareAndSetState方法進行狀態管理。 - 阻塞
通過LockSupport.park()和LockSupport.unpark()實現線程的阻塞和釋放。LockSupport類用于創建鎖和其他同步工具類的基本線程阻塞原語。park操作是不可重入的,類似于二值信號量,如果先unpark再park線程不會阻塞,且park可以被中斷。 - 隊列管理
AQS中定義了Node類,每個Node有各自的狀態并且維護了一個prev和一個next用以形成隊列結構。AQS保存了一個head節點和一個tail節點。形成的等待隊列實際上可以理解為是CLH鎖隊列的一個變種。
CLH經常用于自旋鎖,其維護了一個節點,node中用locked表示線程狀態,如果true則表示正在申請鎖或者已經得到鎖,false則表示已經釋放鎖。在lock方法中節點將檢查前驅節點的locked狀態,如果為true則繼續進入循環直到前驅節點為false標記自己釋放了鎖。unlock操作則需要將locked置為false。
在AQS中,節點的狀態不用于控制自旋而是用來控制阻塞。當前面節點release的時候,當前節點應當被喚醒。
有了這些說明,大家對AQS應該有了一個基本的了解,在后面的文章中,我會對AQS中的重要方法進行解釋說明。