ReentrantLock
的實現原理主要涉及到兩個關鍵概念:同步器(Sync
)和 AQS(AbstractQueuedSynchronizer,抽象隊列同步器)。
ReentrantLock
使用 AQS 來實現可重入鎖的機制。AQS 是 Java 并發包中的一個抽象基類,為實現鎖和其他同步器提供了一種統一的框架。ReentrantLock
則是基于 AQS 提供的框架實現的。
以下是 ReentrantLock
的主要實現原理:
1. AQS 的狀態:
AQS 內部維護一個狀態變量,用來表示被保護資源的狀態。對于 ReentrantLock
來說,狀態值表示當前鎖被持有的次數。當狀態為0時表示鎖未被持有,大于0時表示鎖已被某個線程持有。
2. 同步器(Sync)的實現:
ReentrantLock
的內部實現繼承了 AQS,并提供了兩個具體的實現類:NonfairSync
和 FairSync
,分別對應非公平鎖和公平鎖。
NonfairSync
:在嘗試獲取鎖時,不考慮其他線程是否在等待隊列中等待鎖,直接嘗試獲取。FairSync
:在嘗試獲取鎖時,會優先考慮等待時間最長的線程,以實現公平性。
3. AQS 的隊列:
AQS 使用一個雙向鏈表作為等待隊列,將請求鎖但未能成功獲取的線程加入隊列。隊列中的節點代表等待線程。
4. 獲取鎖的流程:
- 當一個線程嘗試獲取鎖時,如果鎖的狀態為0,則表示鎖未被持有,線程可以直接獲取鎖,并將狀態設置為1。
- 如果鎖的狀態不為0,表示鎖已經被其他線程持有,此時線程將被加入等待隊列,并被掛起,直到鎖被釋放。
- 當持有鎖的線程再次嘗試獲取鎖時,AQS 會判斷當前線程是否已經持有鎖。如果是,直接增加狀態值;如果不是,則將該線程加入等待隊列。
5. 釋放鎖的流程:
- 當一個線程釋放鎖時,AQS 會將狀態值減1。
- 如果狀態值為0,表示鎖已經完全釋放,此時會喚醒等待隊列中的下一個線程。
- 如果狀態值不為0,表示鎖仍然被持有,此時直接減少狀態值。
6. 實現可重入性:
ReentrantLock
的實現允許同一個線程多次獲取鎖,這是通過在節點中維護一個記錄線程持有次數的變量來實現的。線程持有鎖時,增加該變量;釋放鎖時,減少該變量。只有當該變量減到0時,才表示鎖完全被釋放。
ReentrantLock 通過 AQS 提供的隊列和狀態管理機制,實現了可重入鎖的機制,保證了鎖的正確性和靈活性。不同的實現類(
NonfairSync和
FairSync`)在獲取鎖的策略上有所區別,分別支持非公平鎖和公平鎖。