java並發編程之ReentrantLock與synchronized區別

構造使用: 源於 java.util.concurrent.lock

ReentrantLock lock = new ReentrantLock(); //參數默認false,不公平鎖 或 Lock lock = new ReentrantLock();

ReentrantLock lock = new ReentrantLock(true); //公平鎖

lock.lock(); //如果被其它資源鎖定,會在此等待鎖釋放,達到暫停的效果

try {

//操作

} finally {

lock.unlock();

}

公平鎖使線程按照請求鎖的順序依次獲得鎖;而不公平鎖則允許直接獲取鎖,在這種情況下,線程有時可以比先請求鎖的其他線程先得到鎖。

為什麼我們不讓所有的鎖都公平呢?在現實中,公平保證了鎖是非常健壯的鎖,有很大的性能成本。要確保公平所需要的記帳(bookkeeping)和同步,就意味著被爭奪的公平鎖要比不公平鎖的吞吐率更低。作為默認設置,應當把公平設置為 false ,除非公平對您的算法至關重要,需要嚴格按照線程排隊的順序對其進行服務。

ReentrantLock 類實現了 Lock ,它擁有與synchronized 相同的併發性和內存語義,但是添加了類似輪詢鎖、定時鎖等候和可中斷鎖等候的一些特性

。此外,它還提供了在激烈爭用情況下更佳的性能。(換句話說,當許多線程都想訪問共享資源時,JVM 可以花更少的時候來調度線程,把更多時間用在執行線程上。

reentrant 鎖意味著什麼呢?簡單來說,它有一個與鎖相關的獲取計數器,如果擁有鎖的某個線程再次得到鎖,那麼獲取計數器就加1,然後鎖需要被釋放兩次才能獲得真正釋放。這模仿了 synchronized 的語義;如果線程進入由線程已經擁有的監控器保護的 synchronized 塊,就允許線程繼續進行,當線程退出第二個(或者後續) synchronized 塊的時候,不釋放鎖,只有線程退出它進入的監控器保護的第一個 synchronized 塊時,才釋放鎖。

java併發編程之ReentrantLock與synchronized區別

內部實現原理:Lock完全用Java寫成,在java這個層面是無關JVM實現的。ReentrantLock把所有Lock接口的操作都委派到一個Sync類上,該類繼承了AbstractQueuedSynchronize。AbstractQueuedSynchronizer會把所有的請求線程構成一個CLH隊列,當一個線程執行完畢(lock.unlock())時會激活自己的後繼節點,但正在執行的線程並不在隊列中,而那些等待執行的線程全部處於阻塞狀態,經過調查線程的顯式阻塞是通過調用LockSupport.park()完成,而LockSupport.park()則調用sun.misc.Unsafe.park()本地方法,再進一步,HotSpot在Linux中中通過調用pthread_mutex_lock函數把線程交給系統內核進行阻塞。 與synchronized相同的是,這也是一個虛擬隊列,不存在隊列實例,僅存在節點之間的前後關係。令人疑惑的是為什麼採用CLH隊列呢?原生的CLH隊列是用於自旋鎖,但Doug Lea把其改造為阻塞鎖。 當有線程競爭鎖時,該線程會首先嚐試獲得鎖,這對於那些已經在隊列中排隊的線程來說顯得不公平,這也是非公平鎖的由來,與synchronized實現類似,這樣會極大提高吞吐量。 如果已經存在Running線程,則新的競爭線程會被追加到隊尾,具體是採用基於CAS的Lock-Free算法,因為線程併發對Tail調用CAS可能會導致其他線程CAS失敗,解決辦法是循環CAS直至成功

。如果面試問起,你就說底層主要靠volatile和CAS操作實現的。

synchronized:我們知道java是用字節碼指令來控制程序(這裡不包括熱點代碼編譯成機器碼)。在字節指令中,存在有synchronized所包含的代碼塊,那麼會形成2段流程的執行。 其實synchronized映射成字節碼指令就是增加來兩個指令:monitorenter和monitorexit。當一條線程進行執行的遇到monitorenter指令的時候,它會去嘗試獲得鎖,如果獲得鎖那麼鎖計數+1(為什麼會加一呢,因為它是一個可重入鎖,所以需要用這個鎖計數判斷鎖的情況),如果沒有獲得鎖,那麼阻塞。當它遇到monitorexit的時候,鎖計數器-1,當計數器為0,那麼就釋放鎖。那實際為啥有2個monitorexit呀? synchronized鎖釋放有兩種機制,一種就是執行完釋放;另外一種就是發送異常,虛擬機釋放。圖中第二個monitorexit就是發生異常時執行的流程,這就是我開頭說的“會有2個流程存在“。

源於:https://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1 該作者闡述超詳細。


分享到:


相關文章: