java并發(fā)之ReentrantLock

ReentrantLock,可重入鎖,支持一個線程對公有資源重復(fù)加鎖贾节。當(dāng)然汁汗,ReentrantLock還支持公平性的獲取鎖和非公平性的獲取鎖。

注:何謂獲取鎖的公平性栗涂?
每一個線程在獲取鎖的時候可能都會排隊(duì)等待知牌,如果在等待時間上,先獲取鎖的線程的請求一定先被滿足戴差,那么這個鎖就是公平的送爸。反之,這個鎖就是不公平的暖释。公平的獲取鎖袭厂,也就是當(dāng)前等待時間最長的線程先獲取鎖。

接下來就源碼對ReentrantLock做詳細(xì)的分析球匕。

ReentrantLock源碼分析

可重入鎖同讀寫鎖一樣纹磺,也是一種自定義同步器。接下來先從構(gòu)造函數(shù)開始亮曹,依次分析可重入鎖的具體實(shí)現(xiàn)橄杨。

構(gòu)造函數(shù)
構(gòu)造函數(shù)

從源碼可以看出:

  • ReentrantLock提供兩個構(gòu)造方法,不帶參數(shù)構(gòu)造方法和帶boolean型參數(shù)fair的構(gòu)造方法照卦;

  • 默認(rèn)不帶參構(gòu)造方法是非公平性的獲取鎖式矫,帶參數(shù)fair的構(gòu)造方法根據(jù)fair的值判斷到底是公平性的獲取鎖還是非公平性的獲取鎖,fair == true時役耕,是公平性的獲取鎖采转,fair == false時,是非公平性的獲取鎖瞬痘。

自定義同步器Sync

ReentrantLock通過自定義同步器來實(shí)現(xiàn)鎖的獲取與釋放故慈,如何實(shí)現(xiàn)自定義同步器在前文java并發(fā)編程之AbstractQueuedSynchronizer 中已經(jīng)做了詳細(xì)的分析,在這里就不再贅述框全,有不了解的小伙伴可以去讀一讀這篇文章察绷。

Sync實(shí)現(xiàn)
對于JDK提供的兩種鎖來說,鎖的競爭其實(shí)就是競爭同步器AQS的同步狀態(tài)state津辩,鎖的釋放也就是釋放同步狀態(tài)拆撼,接下來我們就具體看看相關(guān)的源碼實(shí)現(xiàn)。

  • Sync之非公平鎖的獲取


    Sync之非公平鎖的獲取

    從源碼可以看出喘沿,鎖的獲取主要分這樣幾個步驟:

    1. 獲取當(dāng)前線程以及同步器狀態(tài)state情萤;

    2. 判斷state == 0是否成立:

    • 成立,表示當(dāng)前同步器不存在線程競爭同步狀態(tài)摹恨,可以直接分配給當(dāng)前線程筋岛,設(shè)置同步狀態(tài),并將持有同步狀態(tài)的線程置為當(dāng)前線程晒哄;

    • 否則睁宰,表示當(dāng)前同步器存在線程競爭同步狀態(tài)肪获,跳轉(zhuǎn)到步驟3。

    1. 判斷同步狀態(tài)線程 == 當(dāng)前線程是否成立:
    • 成立柒傻,根據(jù)可重入的定義孝赫,當(dāng)前線程可以獲取同步狀態(tài),獲取并設(shè)置同步狀態(tài)红符;

    • 否則青柄,線程不能獲取同步狀態(tài),返回预侯。

  • Sync之鎖的釋放


    Sync之鎖的釋放

    鎖的釋放其實(shí)就是同步狀態(tài)state的釋放致开,從源碼可以看出:

    1. 計(jì)算新的同步狀態(tài)c;

    2. 如果c == 0萎馅,表明當(dāng)前同步狀態(tài)釋放后無線程占有該同步狀態(tài)双戳,設(shè)置持有同步狀態(tài)線程為null;

    3. 設(shè)置同步狀態(tài)糜芳。

  • Sync之其他重要方法
    當(dāng)然飒货,Sync也提供一些額外的方法便于使用者獲取鎖的持有者以及判斷當(dāng)前是否加鎖等。


    Sync之其它重要方法

從Sync的具體實(shí)現(xiàn)可以看出峭竣,針對重進(jìn)入:

  1. 鎖的再次獲忍粮ā:記錄獲取鎖的線程,每次獲取鎖都需要去識別獲取鎖的線程是否為當(dāng)前站有所的線程皆撩,如果是扣墩,可以再次成功獲取,否則毅访,不能獲取盘榨;

  2. 鎖的最終釋放:線程重復(fù)多次獲取了鎖喻粹,隨后再多次釋放鎖,加鎖其實(shí)是同步狀態(tài)state進(jìn)行自增草巡,當(dāng)然守呜,state也就表示當(dāng)前鎖被相同線程獲取的次數(shù);鎖在釋放時山憨,state會自減查乒,當(dāng)state等于0時表示當(dāng)前線程獲取的鎖已經(jīng)成功被釋放。

公平鎖的實(shí)現(xiàn)
公平性其實(shí)僅僅是針對鎖的獲取而言郁竟,如果一個鎖是公平的玛迄,那個鎖的獲取的順序就應(yīng)該滿足請求的時間順序,換言之也就是FIFO棚亩。對于非公平鎖的獲取nonfairTryAcquire方法的具體實(shí)現(xiàn)蓖议,非公平鎖其實(shí)只需要CAS設(shè)置同步狀態(tài)成功虏杰,當(dāng)前線程也就獲取鎖成功,但是公平鎖的獲取就不一樣了勒虾。

公平鎖的獲取

從源碼可以看出:
公平鎖的獲取多了一個判斷(在源碼中用綠色線標(biāo)注出來的部分)hasQueuedPredecessors()方法纺阔,接下來來看看這個方法到底做了什么來保證了鎖獲取的FIFO。

  • hasQueuedPredecessors實(shí)現(xiàn)


    hasQueuedPredecessors實(shí)現(xiàn)

    該方法是AbstractQueuedSynchronizer提供的一個方法修然,它可以判斷當(dāng)前等待隊(duì)列是否有線程在等待笛钝,如果有返回true,反之返回false愕宋;

在公平鎖的獲取之前加入該判斷是為了確定當(dāng)前線程是否有前驅(qū)節(jié)點(diǎn)玻靡,如果有,表示有線程比當(dāng)前線程更早的請求獲取鎖掏婶,需要等待前驅(qū)線程獲取并釋放時候才能獲取鎖啃奴。

公平鎖與非公平鎖的區(qū)別
之前做過一個測試,5個線程分別獲取2次公平鎖與非公平鎖雄妥,打印獲取鎖的線程和正在等待的線程最蕾,測試結(jié)果如下:

公平鎖與非公平鎖的獲取測試

從對比結(jié)果可以看出,非公平鎖出現(xiàn)了一個線程連續(xù)獲取鎖的情況老厌,那為什么會出現(xiàn)這個情況呢瘟则?回想一下非公平鎖的獲取,當(dāng)一個線程請求獲取鎖的時候枝秤,只需要獲取同步狀態(tài)即可成功的獲取鎖醋拧,在這個前提下,剛釋放鎖的線程再次獲取同步狀態(tài)的幾率會非常大淀弹,這就會使得其他線程只能在同步隊(duì)列中等待丹壕,這樣就可能會導(dǎo)致線程饑餓,但是薇溃,明顯知道它會有這個缺點(diǎn)菌赖,為什么還要被設(shè)置成默認(rèn)的呢?我們再來觀察下上圖的結(jié)果沐序,可以發(fā)現(xiàn)琉用,公平鎖在測試中進(jìn)行了10次切換,但是非公平鎖只有5次切換策幼,這可以說明非公平鎖的開銷會更小一點(diǎn)邑时。我們再來測試一下系統(tǒng)上下文切換的次數(shù)和耗時(測試場景:10個線程,每個線程獲取10w次鎖):
公平鎖與非公平鎖線程上下文切換次數(shù)及耗時

從對比結(jié)果可以看出特姐,公平鎖的總耗時和總切換次數(shù)遠(yuǎn)遠(yuǎn)超過非公平鎖晶丘,公平鎖以大量的線程切換來換取了鎖獲取的FIFO原則,而非公平鎖雖然可能會導(dǎo)致線程饑餓唐含,但是它的線程切換很少铣口,在一定程度上保證了更大的吞吐量滤钱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市脑题,隨后出現(xiàn)的幾起案子件缸,更是在濱河造成了極大的恐慌,老刑警劉巖叔遂,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件他炊,死亡現(xiàn)場離奇詭異,居然都是意外死亡已艰,警方通過查閱死者的電腦和手機(jī)痊末,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哩掺,“玉大人凿叠,你說我怎么就攤上這事〗劳蹋” “怎么了盒件?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舱禽。 經(jīng)常有香客問我炒刁,道長,這世上最難降的妖魔是什么誊稚? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任翔始,我火速辦了婚禮,結(jié)果婚禮上里伯,老公的妹妹穿的比我還像新娘城瞎。我一直安慰自己,他們只是感情好疾瓮,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布脖镀。 她就那樣靜靜地躺著,像睡著了一般爷贫。 火紅的嫁衣襯著肌膚如雪认然。 梳的紋絲不亂的頭發(fā)上补憾,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天漫萄,我揣著相機(jī)與錄音,去河邊找鬼盈匾。 笑死腾务,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的削饵。 我是一名探鬼主播岩瘦,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼未巫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了启昧?” 一聲冷哼從身側(cè)響起叙凡,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎密末,沒想到半個月后握爷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡严里,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年新啼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刹碾。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡燥撞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出迷帜,到底是詐尸還是另有隱情物舒,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布瞬矩,位于F島的核電站茶鉴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏景用。R本人自食惡果不足惜涵叮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伞插。 院中可真熱鬧割粮,春花似錦、人聲如沸媚污。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耗美。三九已至京髓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間商架,已是汗流浹背堰怨。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蛇摸,地道東北人备图。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親揽涮。 傳聞我的和親對象是個殘疾皇子抠藕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容