在看LinkedBlockingQueue的時候,有這么一句話:LinkedBlockingQueue采用可重入鎖(ReentrantLock)來保證在並發情況下的線程安全。
因此,在這進行學習一下什么叫可重入鎖。
一:概述
1.什么是可重入
什么是 “可重入”,可重入就是說某個線程已經獲得某個鎖,可以再次獲取鎖而不會出現死鎖。
2.可重入鎖有
- synchronized
- ReentrantLock
一:java可重入鎖-ReentrantLock實現細節
ReentrantLock支持兩種獲取鎖的方式,一種是公平模型,一種是非公平模型。在繼續之前,咱們先把故事元素轉換為程序元素。
1.咱們先來說說公平鎖模型
初始化時, state=0,表示無人搶占了打水權。這時候,村民A來打水(A線程請求鎖),占了打水權,把state+1,如下所示:
線程A取得了鎖,把 state原子性+1,這時候state被改為1,A線程繼續執行其他任務,然后來了村民B也想打水(線程B請求鎖),線程B無法獲取鎖,生成節點進行排隊,如下圖所示:
初始化的時候,會生成一個空的頭節點,然后才是B線程節點,這時候,如果線程A又請求鎖,是否需要排隊?答案當然是否定的,否則就直接死鎖了。當A再次請求鎖,就相當於是打水期間,同一家人也來打水了,是有特權的,這時候的狀態如下圖所示:
到了這里,相信大家應該明白了什么是可重入鎖了吧。就是一個線程在獲取了鎖之后,再次去獲取了同一個鎖,這時候僅僅是把狀態值進行累加。如果線程A釋放了一次鎖,就成這樣了:
僅僅是把狀態值減了,只有線程A把此鎖全部釋放了,狀態值減到0了,其他線程才有機會獲取鎖。當A把鎖完全釋放后,state恢復為0,然后會通知隊列喚醒B線程節點,使B可以再次競爭鎖。當然,如果B線程后面還有C線程,C線程繼續休眠,除非B執行完了,通知了C線程。注意,當一個線程節點被喚醒然后取得了鎖,對應節點會從隊列中刪除。
2.非公平鎖模型
如果你已經明白了前面講的公平鎖模型,那么非公平鎖模型也就非常容易理解了。當線程A執行完之后,要喚醒線程B是需要時間的,而且線程B醒來后還要再次競爭鎖,所以如果在切換過程當中,來了一個線程C,那么線程C是有可能獲取到鎖的,如果C獲取到了鎖,B就只能繼續乖乖休眠了。這里就不再畫圖說明了