天天看點

Synchronized 與 ReentrantLock 的差別!

Synchronized 與 ReentrantLock 的差別!

之前棧長分享了重入鎖的概念:《到底什麼是重入鎖,拜托,一次搞清楚!》,今天現來深入了解下 Synchronized 與 ReentrantLock 的差別!

可重入性:

從名字上了解,ReenTrantLock的字面意思就是再進入的鎖,其實synchronized關鍵字所使用的鎖也是可重入的,兩者關于這個的差別不大。

兩者都是同一個線程沒進入一次,鎖的計數器都自增1,是以要等到鎖的計數器下降為0時才能釋放鎖。

鎖的實作:

Synchronized是依賴于JVM實作的,而ReenTrantLock是JDK實作的,有什麼差別,說白了就類似于作業系統來控制實作和使用者自己敲代碼實作的差別。前者的實作是比較難見到的,後者有直接的源碼可供閱讀。

性能的差別:

在Synchronized優化以前,synchronized的性能是比ReenTrantLock差很多的,但是自從Synchronized引入了偏向鎖,輕量級鎖(自旋鎖)後,兩者的性能就差不多了。

在兩種方法都可用的情況下,官方甚至建議使用synchronized,其實synchronized的優化我感覺就借鑒了ReenTrantLock中的CAS技術。都是試圖在使用者态就把加鎖問題解決,避免進入核心态的線程阻塞。

功能差別:

便利性:很明顯Synchronized的使用比較友善簡潔,并且由編譯器去保證鎖的加鎖和釋放,而ReenTrantLock需要手工聲明來加鎖和釋放鎖,為了避免忘記手工釋放鎖造成死鎖,是以最好在finally中聲明釋放鎖。

鎖的細粒度和靈活度:很明顯ReenTrantLock優于Synchronized

ReenTrantLock獨有的能力:

1.ReenTrantLock可以指定是公平鎖還是非公平鎖。而synchronized隻能是非公平鎖。所謂的公平鎖就是先等待的線程先獲得鎖。

2.ReenTrantLock提供了一個Condition(條件)類,用來實作分組喚醒需要喚醒的線程們,而不是像synchronized要麼随機喚醒一個線程要麼喚醒全部線程。

3.ReenTrantLock提供了一種能夠中斷等待鎖的線程的機制,通過lock.lockInterruptibly()來實作這個機制。

ReenTrantLock實作的原理:

在網上看到相關的源碼分析,本來這塊應該是本文的核心,但是感覺比較複雜就不一一詳解了,簡單來說,ReenTrantLock的實作是一種自旋鎖,通過循環調用CAS操作來實作加鎖。

它的性能比較好也是因為避免了使線程進入核心态的阻塞狀态。想盡辦法避免線程進入核心的阻塞狀态是我們去分析和了解鎖設計的關鍵鑰匙。

什麼情況下使用ReenTrantLock:

答案是,如果你需要實作ReenTrantLock的三個獨有功能時。