可重入的讀寫鎖 - ReentrantReadWriteLock 及 AQS 源碼分析

      網(wǎng)友投稿 783 2025-03-31

      1 讀寫鎖維護了一對相關(guān)的鎖,一個用于只讀操作,一個用于寫入操作。

      只要沒有writer,讀鎖可以由多個reader線程同時保持。

      寫鎖是獨占的。

      互斥鎖一次只允許一個線程訪問共享數(shù)據(jù),哪怕是只讀

      讀寫鎖允許對共享數(shù)據(jù)進行更高性能的并發(fā)訪問

      對于寫操作,一次只有一個線程(write線程)可修改共享數(shù)據(jù)

      對于讀操作,允許任意數(shù)量的線程同時讀取

      互斥鎖相比,使用讀寫鎖能否提升性能則取決于讀寫操作期間讀取數(shù)據(jù)相對于修改數(shù)據(jù)的頻率,以及數(shù)據(jù)的爭用,即在同一時間試圖對該數(shù)據(jù)執(zhí)行讀取或?qū)懭氩僮鞯木€程數(shù)。

      讀寫鎖適用于讀多寫少的場景。

      2 可重入讀寫鎖 ReentrantReadWriteLock

      2.1 屬性

      ReentrantReadWriteLock 基于 AbstractQueuedSynchronizer實現(xiàn),具有如下屬性

      獲取順序:此類不會將讀/寫者優(yōu)先強加給鎖訪問的排序

      非公平模式(默認)

      連續(xù)競爭的非公平鎖可能無限期地推遲一個或多個reader或writer線程,但吞吐量通常要高于公平鎖

      公平模式

      線程利用一個近似到達順序的策略來競爭進入。

      當釋放當前持有的鎖時,可以為等待時間最長的單個writer線程分配寫鎖,如果有一組等待時間大于所有正在等待的writer線程的reader,將為該組分配讀鎖。

      試圖獲得公平寫入鎖的非重入的線程將會阻塞,除非讀取鎖和寫入鎖都自由(這意味著沒有等待線程)。

      重入

      此鎖允許reader和writer按照 ReentrantLock 的樣式重新獲取讀/寫鎖。在寫線程保持的所有寫鎖都已釋放后,才允許重入reader使用讀鎖

      writer可以獲取讀取鎖,但reader不能獲取寫入鎖。

      鎖降級

      重入還允許從寫鎖降級為讀鎖,實現(xiàn)方式是:先獲取寫鎖,然后獲取讀取鎖,最后釋放寫鎖。但是,從讀取鎖升級到寫入鎖是不可能的。

      鎖獲取的中斷

      讀鎖和寫鎖都支持鎖獲取期間的中斷。

      Condition 支持

      寫鎖提供了一個 Condition 實現(xiàn),對于寫鎖來說,該實現(xiàn)的行為與 ReentrantLock.newCondition() 提供的 Condition 實現(xiàn)對 ReentrantLock 所做的行為相同。當然,此 Condition 只能用于寫鎖。

      讀鎖不支持 Condition,readLock().newCondition() 會拋UnsupportedOperationException

      監(jiān)測

      此類支持一些確定是讀鎖還是寫鎖的方法。這些方法設計用于監(jiān)視系統(tǒng)狀態(tài),而不是同步控制。

      3 AQS

      記錄當前加鎖的是哪個線程,初始化狀態(tài)下,這個變量是null

      接著線程1跑過來調(diào)用ReentrantLock的lock()方法嘗試進行加鎖,這個加鎖的過程,直接就是用CAS操作將state值從0變?yōu)?。

      如果之前沒人加過鎖,那么state的值肯定是0,此時線程1就可以加鎖成功。

      一旦線程1加鎖成功了之后,就可以設置當前加鎖線程是自己。

      線程1跑過來加鎖的一個過程

      加鎖線程變量

      Reentrant打頭,意思是一個可重入鎖。

      可重入鎖就是你可以對一個ReentrantLock對象多次執(zhí)行l(wèi)ock()加鎖和unlock()釋放鎖,也就是可以對一個鎖加多次,叫做可重入加鎖。

      看明白了那個state變量之后,就知道了如何進行可重入加鎖!

      其實每次線程1可重入加鎖一次,會判斷一下當前加鎖線程就是自己,那么他自己就可以可重入多次加鎖,每次加鎖就是把state的值給累加1,別的沒啥變化。

      接著,如果線程1加鎖了之后,線程2跑過來加鎖會怎么樣呢?

      3.2 我們來看看鎖的互斥是如何實現(xiàn)的

      線程2跑過來一下看到,哎呀!state的值不是0啊?所以CAS操作將state從0變?yōu)?的過程會失敗,因為state的值當前為1,說明已經(jīng)有人加鎖了!

      接著線程2會看一下,是不是自己之前加的鎖啊?當然不是了,“加鎖線程”這個變量明確記錄了是線程1占用了這個鎖,所以線程2此時就是加鎖失敗。

      一起來感受一下線程2的絕望心路

      接著,線程2會將自己放入AQS中的一個等待隊列,因為自己嘗試加鎖失敗了,此時就要將自己放入隊列中來等待,等待線程1釋放鎖之后,自己就可以重新嘗試加鎖了

      所以大家可以看到,AQS是如此的核心!AQS內(nèi)部還有一個等待隊列,專門放那些加鎖失敗的線程!

      同樣,給大家來一張圖,一起感受一下:

      接著,線程1在執(zhí)行完自己的業(yè)務邏輯代碼之后,就會釋放鎖!

      他釋放鎖的過程非常的簡單,就是將AQS內(nèi)的state變量的值遞減1,如果state值為0,則徹底釋放鎖,會將“加鎖線程”變量也設置為null!

      附圖

      接下來,會從等待隊列的隊頭喚醒線程2重新嘗試加鎖。

      好!線程2現(xiàn)在就重新嘗試加鎖,這時還是用CAS操作將state從0變?yōu)?,此時就會成功,成功之后代表加鎖成功,就會將state設置為1。

      此外,還要把“加鎖線程”設置為線程2自己,同時線程2自己就從等待隊列中出隊了。

      最后再來一張圖,大家來看看這個過程。

      ReentrantLock,它是可重入的獨占鎖,內(nèi)部的 Sync 類實現(xiàn)了 tryAcquire(int)、tryRelease(int) 方法,并用狀態(tài)的值來表示重入次數(shù),加鎖或重入鎖時狀態(tài)加 1,釋放鎖時狀態(tài)減 1,狀態(tài)值等于 0 表示鎖空閑。

      CountDownLatch,它是一個關(guān)卡,在條件滿足前阻塞所有等待線程,條件滿足后允許所有線程通過。內(nèi)部類 Sync 把狀態(tài)初始化為大于 0 的某個值,當狀態(tài)大于 0 時所有wait線程阻塞,每調(diào)用一次 countDown 方法就把狀態(tài)值減 1,減為 0 時允許所有線程通過。利用了AQS的共享模式。

      4 AQS只有一個狀態(tài),那么如何表示 多個讀鎖 與 單個寫鎖

      ReentrantLock 里,狀態(tài)值表示重入計數(shù)

      現(xiàn)在如何在AQS里表示每個讀鎖、寫鎖的重入次數(shù)呢

      如何實現(xiàn)讀鎖、寫鎖的公平性呢

      一個狀態(tài)是沒法既表示讀鎖,又表示寫鎖的,顯然不夠用啊,那就辦成兩份用了!

      狀態(tài)的高位部分表示讀鎖,低位表示寫鎖

      由于寫鎖只有一個,所以寫鎖的重入計數(shù)也解決了,這也會導致寫鎖可重入的次數(shù)減小。

      由于讀鎖可以同時有多個,肯定不能再用辦成兩份用的方法來處理了

      但我們有 ThreadLocal,可以把線程重入讀鎖的次數(shù)作為值存在 ThreadLocal

      可重入的讀寫鎖 - ReentrantReadWriteLock 及 AQS 源碼分析

      對于公平性的實現(xiàn),可以通過AQS的等待隊列和它的抽象方法來控制

      在狀態(tài)值的另一半里存儲當前持有讀鎖的線程數(shù)。

      如果讀線程申請讀鎖,當前寫鎖重入次數(shù)不為 0 時,則等待,否則可以馬上分配

      如果是寫線程申請寫鎖,當前狀態(tài)為 0 則可以馬上分配,否則等待。

      任務調(diào)度

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:定制系統(tǒng),讓這家初創(chuàng)企業(yè)領(lǐng)跑數(shù)字化
      下一篇:包含gpaas apaas的詞條
      相關(guān)文章
      亚洲天堂在线播放| 国产偷v国产偷v亚洲高清| 亚洲AV成人片色在线观看高潮| 色久悠悠婷婷综合在线亚洲| 亚洲最大av无码网址| 亚洲国产精品无码久久久久久曰 | 亚洲动漫精品无码av天堂| 亚洲伊人久久综合影院| 亚洲国产精品无码久久九九| 亚洲美日韩Av中文字幕无码久久久妻妇 | 黑人大战亚洲人精品一区| 中文字幕在亚洲第一在线 | 久久久久国产亚洲AV麻豆 | 亚洲乱色熟女一区二区三区丝袜| 亚洲熟女一区二区三区| 亚洲精品国产精品乱码视色| 久久九九亚洲精品| 亚洲另类激情综合偷自拍| 久久久久亚洲AV成人片| 亚洲欧洲尹人香蕉综合| 亚洲人和日本人jizz| 中文字幕在线日亚洲9| 亚洲AV永久无码精品网站在线观看| 亚洲hairy多毛pics大全| 国产亚洲精彩视频| av在线亚洲欧洲日产一区二区| 久久亚洲中文字幕精品一区| 国产精品亚洲片在线| 亚洲一区二区三区电影| 亚洲最新中文字幕| 亚洲色大成WWW亚洲女子| 老子影院午夜伦不卡亚洲| 亚洲Av无码国产情品久久| 国产亚洲成人在线播放va| 九月丁香婷婷亚洲综合色| 亚洲网站在线播放| 亚洲久悠悠色悠在线播放| 国产精品亚洲AV三区| 91麻豆国产自产在线观看亚洲 | 亚洲色丰满少妇高潮18p| 亚洲AV无码专区日韩|