ReentrantLock實現原理及原始碼分析
ReentrantLock實現原理及原始碼分析
ReentrantLock是Java併發包中提供的一個可重入的互斥鎖。ReentrantLock和synchronized在基本用法,行為語義上都是類似的,同樣都具有可重入性。只不過相比原生的Synchronized,ReentrantLock增加了一些高階的擴充套件功能,比如它可以實現公平鎖,同時也可以繫結多個Conditon。
可重入性/公平鎖/非公平鎖
可重入性
所謂的可重入性,就是可以支援一個執行緒對鎖的重複獲取
公平鎖/非公平鎖
所謂公平鎖,顧名思義,意指鎖的獲取策略相對公平,當多個執行緒在獲取同一個鎖時,必須按照鎖的申請時間來依次獲得鎖,排排隊,不能插隊;非公平鎖則不同,當鎖被釋放時,等待中的執行緒均有機會獲得鎖。synchronized是非公平鎖,ReentrantLock預設也是非公平的,但是可以通過帶boolean引數的構造方法指定使用公平鎖,但非公平鎖的效能一般要優於公平鎖。
synchronized是Java原生的互斥同步鎖,使用方便,對於synchronized修飾的方法或同步塊,無需再顯式釋放鎖。synchronized底層是通過monitorenter和monitorexit兩個位元組碼指令來實現加鎖解鎖操作的。而ReentrantLock做為API層面的互斥鎖,需要顯式地去加鎖解鎖。
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // 加鎖 try { // ... 函式主題 } finally { lock.unlock() //解鎖 } } }
ReentrantLock是基於AQS的,AQS是Java併發包中眾多同步元件的構建基礎,它通過一個int型別的狀態變數state和一個FIFO佇列來完成共享資源的獲取,執行緒的排隊等待等。AQS是個底層框架,採用模板方法模式,它定義了通用的較為複雜的邏輯骨架,比如執行緒的排隊,阻塞,喚醒等,將這些複雜但實質通用的部分抽取出來,這些都是需要構建同步元件的使用者無需關心的,使用者僅需重寫一些簡單的指定的方法即可(其實就是對於共享變數state的一些簡單的獲取釋放的操作)。
上面簡單介紹了下AQS,詳細內容可參考本人的另一篇文章《Java併發包基石-AQS詳解》,此處就不再贅述了。先來看常用的幾個方法,我們從上往下推。
無參構造器(預設為非公平鎖)
public ReentrantLock() {
sync = new NonfairSync();//預設是公平的
}
sync是ReentrantLock內部實現的一個同步元件,它是Reentrantlock的一個靜態內部類,繼承於AQS,後面我們再分析。
帶布林值的構造器(是否公平)
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();//fair為true,公平鎖;反之,非公平鎖
}
看到了吧,此處可以指定是否採用公平鎖,FailSync和NonFailSync亦為Reentrantlock的靜態內部類,都繼承於Sync。
再來看看幾個我們常用到的方法
lock()
public void lock() {
sync.lock();//代理到Sync的lock方法上
}
Sync的lock方法是抽象的,實際的lock會代理到FairSync或是NonFairSync上(根據使用者的選擇來決定,公平鎖還是非公平鎖)
lockInterruptibly()
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);//代理到sync的相應方法上,同lock方法的區別是此方法響應中斷
}
此方法響應中斷,當執行緒在阻塞中的時候,若被中斷,會丟擲InterruptedException異常
tryLock()
public boolean tryLock() {
return sync.nonfairTryAcquire(1);//代理到sync的相應方法上
}
tryLock,嘗試獲取鎖,成功則直接返回true,不成功也不耽擱時間,立即返回false。
unlock()
public void unlock() {
sync.release(1);//釋放鎖
}
釋放鎖,呼叫sync的release方法,其實是AQS的release邏輯。
newCondition()
獲取一個conditon,ReentrantLock支援多個Condition
public Condition newCondition() {
return sync.newCondition();
}
小結
其實從上面這寫方法的介紹,我們都能大概梳理出ReentrantLock的處理邏輯,其內部定義了三個重要的靜態內部類,Sync,NonFairSync,FairSync。Sync作為ReentrantLock中公用的同步元件,繼承了AQS(要利用AQS複雜的頂層邏輯嘛,執行緒排隊,阻塞,喚醒等等);NonFairSync和FairSync則都繼承Sync,呼叫Sync的公用邏輯,然後再在各自內部完成自己特定的邏輯(公平或非公平)。
https://www.cnblogs.com/chengxiao/p/7255941.html