java讀寫鎖(ReentrantReadWriteLock)的實現(xiàn)原理

轉(zhuǎn)自? https://www.cnblogs.com/faunjoe88/p/7928757.html

公平讀寫鎖

ReentrantReadWriteLock的鎖策略有兩種淹办,分為公平策略和非公平策略,兩者有些小區(qū)別,為便于理解,

本小節(jié)將以示例的形式來說明多線程下,使用公平策略的讀寫鎖是如何處理的。

首先看一下即將出場的伙伴們,我們一共會出場幾個線程襟士,還有用于實現(xiàn)讀寫機制的AQS同步器隊列。

每個線程中的 R(0)W(0)表示當(dāng)前線程占用了多少讀寫鎖嚷量。

接下來陋桂,我們一步步來看在公平策略下多線程并發(fā)的讀寫機制是怎樣的。

1.線程A請求一個讀鎖蝶溶,此時無人競爭鎖嗜历,A獲取讀鎖1,即線程A重入次數(shù)為1,如下所示:


2.線程B請求一個讀鎖秸脱,由于AQS中沒有等待節(jié)點落包,當(dāng)前處于讀鎖占有狀態(tài)(線程A占有1個讀鎖),所以B成功獲取讀鎖摊唇,如下所示:


3.這時候咐蝇,線程C請求一個寫鎖,由于當(dāng)前其他兩個線程擁有讀鎖巷查,寫鎖獲取失敗有序,線程C入隊列,如下所示:


AQS初始化會創(chuàng)建一個空的頭節(jié)點岛请,C入隊列旭寿,然后會休眠,等待其他線程釋放鎖喚醒崇败。

4.線程D也來了盅称,線程D想獲取一個讀鎖,雖然當(dāng)于處于讀鎖占有階段后室,但是目前D不占有任何數(shù)量的讀鎖缩膝,

而且同步器隊列中已經(jīng)有等待節(jié)點,這時候岸霹,由于公平策略疾层,D不得已,一個字贡避,等痛黎,如下圖所示:


5.這時候,線程A執(zhí)行完了刮吧,釋放了讀鎖湖饱,由于B仍然占有讀鎖,所以釋放后讀鎖仍然沒有完全釋放杀捻,寫鎖仍然沒有機會執(zhí)行琉历,如下圖所示:

6.這次,B也執(zhí)行完了水醋,執(zhí)行完后,讀鎖全部釋放彪置,這時候會喚醒排在同步器隊頭的節(jié)點C拄踪,C成功獲取一個寫鎖,如下圖所示:

7.一旦任何一個線程獲取了寫鎖拳魁,除了該線程自己惶桐,其它線程都將無法獲取讀鎖和寫鎖,這時候,線程C再次請求一個讀鎖姚糊,這是允許的贿衍,

但反過來如果一個線程先獲取了讀鎖,再獲取寫法則是不行的救恨。這時候的狀態(tài)如下圖所示:

8.這時候假設(shè)線程E也來了贸辈,E想獲取讀鎖,由于當(dāng)前處于寫鎖狀態(tài)肠槽,直接入隊擎淤,如下所示:

9.這會C終于把活干完了,把讀鎖和寫鎖都給釋放了秸仙,然后線程D被喚醒嘴拢,獲取了讀鎖,如下圖所示:

10.這時候寂纪,如果再來一個線程席吴,比如A评甜,也想獲取讀鎖哎甲,由于節(jié)點中還有線程E在等待,而且當(dāng)前線程A沒有獲取任何讀鎖奴饮,不是重入狀態(tài)襟交,所以只能置入隊尾迈倍,如下圖所示:

11.這時候,如果D再次調(diào)用了一次獲取讀鎖捣域,由于D屬于可重入狀態(tài)啼染,所以直接把讀鎖+1即可,如下圖所示:

12.由于D獲取的是讀鎖焕梅,同步隊列中的E等待的也是讀鎖迹鹅,所以E會被喚醒,獲取讀鎖繼續(xù)執(zhí)行贞言,如下圖所示:

13.同樣的斜棚,由于線程A獲取的是讀鎖,在E執(zhí)行后该窗,會喚醒線程A弟蚀,A也可以獲得讀鎖,并繼續(xù)執(zhí)行酗失,如下圖所示:

14.最后大家各自執(zhí)行义钉,悄然退場。

非公平讀寫鎖

接下來我們再來看一下非公平策略讀寫鎖機制又是如何的规肴,為了更好的對比捶闸,我們沿用公平鎖的流程夜畴。

由于獲取讀鎖的邏輯比較復(fù)雜,我們在這里先簡單進(jìn)行歸納:

a. 如果當(dāng)前全局處于無鎖狀態(tài)删壮,則當(dāng)前線程獲取讀鎖

b. 如果當(dāng)前全局處于讀鎖狀態(tài)贪绘,且隊列中沒有等待線程,則當(dāng)前線程獲取讀鎖

c. 如果當(dāng)前全局處于寫鎖占用狀態(tài)(并且不是當(dāng)前線程占有)央碟,則當(dāng)前線程入隊尾

d. 如果當(dāng)前全局處于讀鎖狀態(tài)税灌,且等待隊列中第一個等待線程想獲取寫鎖,那么當(dāng)前線程能夠獲取到讀鎖的條件為:當(dāng)前線程獲取了寫鎖硬耍,還未釋放垄琐;當(dāng)前線程獲取了讀鎖,這一次只是重入讀鎖而已经柴;其它情況當(dāng)前線程入隊尾狸窘。之所以這樣處理一方面是為了效率,一方面是為了避免想獲取寫鎖的線程饑餓坯认,老是得不到執(zhí)行的機會

e. 如果當(dāng)前全局處于讀鎖狀態(tài)翻擒,且等待隊列中第一個等待線程不是寫鎖,則當(dāng)前線程可以搶占讀鎖

獲取寫鎖相對就比較簡單了牛哺,規(guī)則如下:

h. 如果當(dāng)前處于無鎖狀態(tài)陋气,則當(dāng)前線程獲取寫鎖

i. 如果當(dāng)前全局處于讀鎖狀態(tài),當(dāng)前線程入隊尾

j. 如果當(dāng)前全局處于寫鎖狀態(tài)引润,除非是重入獲取寫鎖巩趁,否則入隊尾

接下來我們看一遍流程:

1.線程A請求一個讀鎖,全局處于無鎖狀態(tài)淳附,根據(jù)規(guī)則a议慰,線程A獲取了鎖,如下圖所示:

2.線程B請求一個讀鎖奴曙,根據(jù)規(guī)則b别凹,線程B可以獲取到讀鎖

3.這時候,線程C請求一個寫鎖洽糟,由于當(dāng)前其他兩個線程擁有讀鎖炉菲,寫鎖獲取失敗,線程C入隊列(根據(jù)規(guī)則i)坤溃,如下所示:

AQS初始化會創(chuàng)建一個空的頭節(jié)點拍霜,C入隊列,然后會休眠薪介,等待其他線程釋放鎖喚醒沉御。

4.線程D也來了,線程D想獲取一個讀鎖昭灵,根據(jù)讀鎖規(guī)則d吠裆,隊列中第一個等待線程C請求的是寫鎖,為避免寫鎖遲遲獲取不到烂完,并且線程D不是重入獲取讀鎖试疙,所以線程D也入隊,如下圖所示:

5.這時候抠蚣,線程A執(zhí)行完了祝旷,釋放了讀鎖,由于B仍然占有讀鎖嘶窄,所以釋放后讀鎖仍然沒有完全釋放怀跛,寫鎖仍然沒有機會執(zhí)行,如下圖所示:

6.這次柄冲,B也執(zhí)行完了吻谋,執(zhí)行完后,讀鎖全部釋放现横,這時候會喚醒排在同步器隊頭的節(jié)點C漓拾,C成功獲取一個寫鎖,如下圖所示:

7.一旦任何一個線程獲取了寫鎖戒祠,除了該線程自己骇两,其它線程都將無法獲取讀鎖和寫鎖,這時候姜盈,線程C再次請求一個讀鎖低千,這是允許的,

但反過來如果一個線程先獲取了讀鎖馏颂,再獲取寫鎖則是不行的示血。這時候的狀態(tài)如下圖所示:

8.這時候假設(shè)線程E也來了,E想獲取讀鎖饱亮,由于當(dāng)前處于寫鎖狀態(tài)矾芙,直接入隊,如下所示:

9.這會C終于把活干完了近上,把讀鎖和寫鎖都給釋放了剔宪,然后線程D被喚醒,獲取了讀鎖壹无,如下圖所示:

10.這時候葱绒,如果再來一個線程,比如A斗锭,也想獲取讀鎖地淀,雖然等待隊列中,E線程剛好還沒被喚醒岖是,

但A線程是可以搶占讀鎖的(這里假設(shè)搶占到了)帮毁,這個跟公平鎖有明顯的區(qū)別实苞,如下圖所示:

11.這時候,如果D再次調(diào)用了一次獲取讀鎖烈疚,由于D屬于可重入狀態(tài)黔牵,所以直接把讀鎖+1即可,如下圖所示:

12.由于當(dāng)前狀態(tài)下處于讀鎖狀態(tài)爷肝,前面的線程D其實醒來后猾浦,是會同時喚醒線程E的,所以線程E也醒過來繼續(xù)干活了灯抛,如下圖所示:

13.同步隊列中沒有等待線程了金赦,各個線程執(zhí)行完后,一切相安無事了对嚼。

總結(jié)

考慮到業(yè)務(wù)的多樣化夹抗,java5中提供的并發(fā)包中的工具類大部分都同時提供了公平及非公平策略,這兩種策略下猪半,一般而言兔朦,非公平鎖吞吐會比較大,所以默認(rèn)情況下都是使用的非公平策略磨确。

本篇試圖以盡量簡單的方式來闡明讀寫鎖的實現(xiàn)機制沽甥,為了直觀,我們只考慮簡單抽象的方式乏奥,實際在實現(xiàn)的時候摆舟,會使用CAS去競爭鎖。特別是在非公平策略中的第10個步驟邓了,這種情況下有可能E先獲取了讀鎖恨诱。很多時候,我們在大致了解了實現(xiàn)步驟骗炉,流程之后照宝,再去品味源碼,就會更加的輕松句葵。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厕鹃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子乍丈,更是在濱河造成了極大的恐慌剂碴,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轻专,死亡現(xiàn)場離奇詭異忆矛,居然都是意外死亡,警方通過查閱死者的電腦和手機请垛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門催训,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洽议,“玉大人,你說我怎么就攤上這事漫拭〗柿澹” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵嫂侍,是天一觀的道長。 經(jīng)常有香客問我荚坞,道長挑宠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任颓影,我火速辦了婚禮各淀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诡挂。我一直安慰自己碎浇,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布璃俗。 她就那樣靜靜地躺著奴璃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪城豁。 梳的紋絲不亂的頭發(fā)上苟穆,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音唱星,去河邊找鬼雳旅。 笑死,一個胖子當(dāng)著我的面吹牛间聊,可吹牛的內(nèi)容都是我干的攒盈。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼哎榴,長吁一口氣:“原來是場噩夢啊……” “哼型豁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起叹话,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤偷遗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后驼壶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氏豌,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年热凹,在試婚紗的時候發(fā)現(xiàn)自己被綠了泵喘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泪电。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖纪铺,靈堂內(nèi)的尸體忽然破棺而出相速,到底是詐尸還是另有隱情,我是刑警寧澤鲜锚,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布突诬,位于F島的核電站,受9級特大地震影響芜繁,放射性物質(zhì)發(fā)生泄漏旺隙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一骏令、第九天 我趴在偏房一處隱蔽的房頂上張望蔬捷。 院中可真熱鬧,春花似錦榔袋、人聲如沸周拐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妥粟。三九已至,卻和暖如春聪黎,著一層夾襖步出監(jiān)牢的瞬間罕容,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工稿饰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锦秒,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓喉镰,卻偏偏與公主長得像旅择,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子侣姆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348