前言自己開的坑,跪著也要填完,歡迎來到Java併發程式設計系列第五篇ReentrantLock,文章風格依然是圖文並茂,通俗易懂,本文帶讀者們深入理解ReentrantLock設計思想。認識下Reentran
2021-06-18 05:59:05
自己開的坑,跪著也要填完,歡迎來到Java併發程式設計系列第五篇ReentrantLock
,文章風格依然是圖文並茂,通俗易懂,本文帶讀者們深入理解ReentrantLock
設計思想。
先帶讀者們和ReentrantLock
見個面,簡單的認識下什麼是ReentrantLock
。
ReentrantLock
是可重入的互斥鎖,雖然具有與synchronized
相同功能,但是會比synchronized
更加靈活(具有更多的方法)。
ReentrantLock
底層基於AbstractQueuedSynchronizer
實現,AbstractQueuedSynchronizer
在前一篇已經詳細解剖過了,本文不做過多描述,但是會簡單的介紹下,照顧小白。
AbstractQueuedSynchronizer
抽象類定義了一套多執行緒訪問共享資源的同步模板,解決了實現同步器時涉及的大量細節問題,能夠極大地減少實現工作,用大白話來說,AbstractQueuedSynchronizer
為加鎖和解鎖過程提供了統一的模板函數,只有少量細節由子類自己決定。
經過上述介紹,相信讀者們對ReentrantLock
有了初步的印象,下面開始發車了~
學任何知識的第一件事,就是看清它的全貌,梳理出整體結構與主流程,之後逐個擊破,所以帶讀者們先看下ReentrantLock
整體結構組成,對它的實現有個大致的瞭解。
上圖可以看出來,ReentrantLock
整體結構還是非常簡單,給讀者們分析一波,為什麼ReentrantLock
結構是這樣設計的,首先ReentrantLock
實現了Lock
介面,Lock
介面是Java
中對鎖操作行為的統一規範,遵守規則規範是守法公民的基本素養,合情合理,Lock
介面的定義如下
Lock
介面定義的函數不多,接下來ReentrantLock
要去實現這些函數,遵循著解耦可擴展設計,ReentrantLock
內部定義了專門的元件Sync
, Sync
繼承AbstractQueuedSynchronizer
提供釋放資源的實現,NonfairSync
和FairSync
是基於Sync
擴展的子類,即ReentrantLock
的非公平模式與公平模式,它們作為Lock
介面功能的基本實現。
大白話來說,企業的老闆,為了響應政府的政策,需要對企業內部做調整,但是政府每年政策都不一樣,每次都要自己去親力親為,索性長痛不如短痛,專門成立一個政策應對部門,以後這些事情都交予這個部門去做,老闆只需要指揮它們就好了。
ReentrantLock
結構組成讀者們也清楚了,下面我只需對Sync、NonfairSync、FairSync
逐個擊破,ReentrantLock
自然水到渠成。
小貼士:在
ReentrantLock
中,它對AbstractQueuedSynchronizer
的state
狀態值定義為執行緒獲取該鎖的重入次數,state
狀態值為0
表示當前沒有被任何執行緒持有,state
狀態值為1
表示被其他執行緒持有,因為支援可重入,如果是持有鎖的執行緒,再次獲取同一把鎖,直接成功,並且state
狀態值+1
,執行緒釋放鎖state
狀態值-1
,同理重入多次鎖的執行緒,需要釋放相應的次數。
Sync
可以說是ReentrantLock
的親兒子,它寄託了全村的希望,完美的繼承了AbstractQueuedSynchronizer
,是ReentrantLock
的核心,後面的NonfairSync
與FairSync
都是基於Sync
擴展出來的子類。
聽我吹完了Sync
,下面就來看看Sync
類定義的核心部分
我發現Sync
有點偏心,首先Sync
實現釋放資源的細節(A Q S
留給子類實現的tryRelease
),然後聲明瞭獲取鎖的抽象函數(lock
),子類根據業務實現,目前看來還是很公平,但是Sync
還定義了一個nonfairTryAcquire
函數,這個函數是專門給NonfairSync
使用的,FairSync
卻沒有這種待遇,所以說Sync
偏心。
Sync
邏輯都比較簡單,實現了A Q S
類的釋放資源(tryRelease
),然後抽象了一個獲取鎖的函數讓子類自行實現(lock
),再加一個偏心的函數nonfairTryAcquire
,但是再怎麼簡單,圖還是要有的,這是我讀者們的福利。
下面放一張tryRelease
流程圖,在後續的NonfairSync、FairSync
都會有全面的流程。
現在我們把視線轉移到NonfairSync
,在ReentrantLock
中支援兩種獲取鎖的策略,分別是非公平策略與公平策略,NonfairSync
就是非公平策略。
此時讀者會有問道,什麼是非公平策略?
在說非公平策略前,先簡單的說下A Q S(AbstractQueuedSynchronizer)
流程,A Q S
為加鎖和解鎖過程提供了統一的模板函數,加鎖與解鎖的模板流程是,獲取鎖失敗的執行緒,會進入CLH
佇列阻塞,其他執行緒解鎖會喚醒CLH
佇列執行緒,如下圖所示(簡化流程)
上圖中,執行緒釋放鎖時,會喚醒CLH
佇列阻塞的執行緒,重新競爭鎖,要注意,此時可能還有非CLH
佇列的執行緒參與競爭,所以非公平就體現在這裡,非CLH
佇列執行緒與CLH
佇列執行緒競爭,各憑本事,不會因為你是CLH
佇列的執行緒,排了很久的隊,就把鎖讓給你。
瞭解了什麼是非公平策略,我們再來看看NonfairSync
類定義
NonfairSync
繼承Sync
實現了lock
函數,lock
函數也非常簡單,C A S
設定狀態值state
為1
代表獲取鎖成功,否則執行A Q S
的acquire
函數(獲取鎖模板),另外NonfairSync
還實現了A Q S
留給子類實現的tryAcquire
函數(獲取資源),這個被Sync
寵幸的幸運兒,直接使用Sync
提供的nonfairTryAcquire
函數來實現tryAcquire
,最後子類實現的tryAcquire
函數在A Q S
的acquire
函數中被使用。
是不是有點繞?沒事帶大家一起縷一縷
首先A Q S
的acquire
函數是獲取鎖的流程模板,模板流程會先執行tryAcquire
函數獲取資源,tryAcquire
函數要子類實現,NonfairSync
作為子類,實現了tryAcquire
函數,具體實現是呼叫了Sync
的nonfairTryAcquire
函數。
接下來,我們再看看Sync
專門給NonfairSync
準備的nonfairTryAcquire
函數邏輯
對上述程式碼邏輯做個簡單的概括,當前執行緒檢視資源是否可獲取:
可獲取,嘗試使用C A S
設定state
為1
,C A S
成功代表獲取資源成功,否則獲取資源失敗
不可獲取,判斷當執行緒是不是持有鎖的執行緒,如果是,state
重入計數,獲取資源成功,否則獲取資源失敗
就兩句話,是不是十分簡單,雖然簡單但我還是畫了一張nonfairTryAcquire
流程圖給讀者們觀賞
有非公平策略,就有公平策略,FairSync
就是ReentrantLock
的公平策略。
所謂公平策略就是,嚴格按照CLH
佇列順序獲取鎖,執行緒釋放鎖時,會喚醒CLH
佇列阻塞的執行緒,重新競爭鎖,要注意,此時可能還有非CLH
佇列的執行緒參與競爭,為了保證公平,一定會讓CLH
佇列執行緒競爭成功,如果非CLH
佇列執行緒一直佔用時間片,那就一直失敗(構建成節點插入到CLH
隊尾,由A S Q
模板流程執行),直到時間片輪到CLH
佇列執行緒為止,所以公平策略的效能會更差。
瞭解了什麼是公平策略,我們再來看看FairSync
類定義
其實我們不難發現FairSync
流程與NonfairSync
基本一致,唯一的區別就是在C A S
執行前,多了一步hasQueuedPredecessors
函數,這一步就是判斷當前執行緒是不是CLH
佇列被喚醒的執行緒,如果是就執行C A S
,否則獲取資源失敗,下面水一張圖
最後帶大家看看ReentrantLock
中是如何實現Lock
的,先看構造器部分
ReentrantLock
預設是使用非公平策略,如果想指定模式,可以通過入參fair
來選擇,這裡就不做過多概述,接下來看看ReentrantLock
對Lock
的實現
是不是特別簡單,ReentrantLock
對Lock
的實現都是基於Sync
來做的,有一種神器在手,天下我有的風範。
Sync
承包了所有事情,為何它如此牛皮,因為Sync
上有AbstractQueuedSynchronizer
老大哥罩著,下有NonfairSync
與FairSync
兩小弟可差遣,所以成為ReentrantLock
的利器也合情合理。
最後畫一張結合A Q S
的流程圖,來結束ReentrantLock
。
不知道各位讀者喜不喜歡,如果喜歡的話請點贊、再看,讓我感受下讀者們的熱情,最後下面會有一個關於閱讀時間的調查,也希望讀者們可以熱情參與,好讓我對發文時間心裡有個B樹。
相關文章
前言自己開的坑,跪著也要填完,歡迎來到Java併發程式設計系列第五篇ReentrantLock,文章風格依然是圖文並茂,通俗易懂,本文帶讀者們深入理解ReentrantLock設計思想。認識下Reentran
2021-06-18 05:59:05
6月17號至18號,攀升DIY電腦旗艦店618活動將進入最終的大促階段。17號、18號這兩天,每天零點整,全店第1至5名消費者有機會免單,全店第6至30名消費者有機會獲得618元現金紅包,全店
2021-06-18 05:58:01
徠卡(Leica)首款手機LeitzPhone1,採用一塊夏普6.6英寸Pro的IGZOOLED曲面屏,解析度為2730×1260,支援240Hz重新整理率(1~240Hz自適應),支援10.7億色顯、2000尼特亮度,20000000:1對比度,
2021-06-18 04:30:22
作者 | 屠敏 2021 年 6 月 17 日,由中國開源軟體推進聯盟(COPU)主辦,賽迪傳媒、《軟體和積體電路》雜誌社聯合承辦,CSDN 獨家直播的「2021 第十六屆開源中國開源世界高峰論壇」在
2021-06-18 03:04:16
618大促期間,三星手機在官網的優惠券出現錯誤,部分消費者發現了其中的錯誤搶購三星的手機,為了保護消費者的合理權益,據悉三星直接給予消費者4000元現金補償。據媒體的報道指出,6
2021-06-18 03:03:54
一提到徠卡公司,大家首先想到的是誰?攝影迷肯定心裡都有一臺徠卡夢,隨隨便便一臺徠卡相機的價格就要20萬了,被認為是相機領域的「愛馬仕」。不過國人熟悉徠卡品牌,很大原因是源自
2021-06-18 03:03:38