最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ReadWriteLock接口及其實(shí)現(xiàn)ReentrantReadWriteLock方法

 更新時(shí)間:2017年06月19日 09:36:24   投稿:jingxian  
下面小編就為大家?guī)?lái)一篇ReadWriteLock接口及其實(shí)現(xiàn)ReentrantReadWriteLock方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

Java并發(fā)包的locks包里的鎖基本上已經(jīng)介紹得差不多了,ReentrantLock重入鎖是個(gè)關(guān)鍵,在清楚的了解了同步器AQS的運(yùn)行機(jī)制后,實(shí)際上再分析這些鎖就會(huì)顯得容易得多,這章節(jié)主講另外一個(gè)重要的鎖——ReentrantReadWriteLock讀寫(xiě)鎖。

ReentrantLock是一個(gè)獨(dú)占鎖,也就是說(shuō)只能由一個(gè)線(xiàn)程獲取鎖,但如果場(chǎng)景是線(xiàn)程只做讀的操作呢?這樣ReentrantLock就不是很合適,讀的線(xiàn)程并不需要保證其線(xiàn)程的安全性,任何一個(gè)線(xiàn)程都能去獲取鎖,只有這樣才能盡可能地保證性能和效率。ReentrantReadWriteLock就是這樣的一個(gè)鎖,在其內(nèi)部分為讀鎖和寫(xiě)鎖,可以有N個(gè)讀操作線(xiàn)程獲取到寫(xiě)鎖,但是只能有1個(gè)寫(xiě)操作線(xiàn)程獲取到寫(xiě)鎖,那么可以預(yù)見(jiàn)的是寫(xiě)鎖是共享鎖(AQS中的共享模式),讀鎖是獨(dú)占鎖(AQS中的獨(dú)占模式)。首先來(lái)看讀寫(xiě)鎖的接口類(lèi):

public interface ReadWriteLock { 
  Lock readLock();  //獲取讀鎖
  Lock writeLock();  //獲取寫(xiě)鎖
 }

可以看到ReadWriteLock接口只定義了兩個(gè)方法,獲取讀鎖和獲取寫(xiě)鎖的方法。下面是ReadWriteLock的實(shí)現(xiàn)類(lèi)——ReentrantReadWriteLock。  

和ReentrantLock類(lèi)似,ReentrantReadWriteLock在其內(nèi)部也是通過(guò)一個(gè)內(nèi)部類(lèi)Sync實(shí)現(xiàn)同步器AQS,同樣也是通過(guò)實(shí)現(xiàn)Sync實(shí)現(xiàn)公平鎖和非公平鎖,這一點(diǎn)的思路和ReentrantLock類(lèi)似。在ReadWriteLock接口中獲取的讀鎖和寫(xiě)鎖是怎么實(shí)現(xiàn)的呢?

//ReentrantReadWriteLock
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync;
public ReentrantReadWriteLock(){
 this(false); //默認(rèn)非公平鎖
}
public ReentrantReadWriteLock(boolean fair) {
 sync = fair ? new FairSync() : new NonfairSync(); //鎖類(lèi)型(公平/非公平)
 readerLock = new ReadLock(this); //構(gòu)造讀鎖
 writerLock = new WriteLock(this); //構(gòu)造寫(xiě)鎖
}
……
public ReentrantReadWriteLock.WriteLock writeLock0{return writerLock;}
public ReentrantReadWriteLock.ReadLock readLock0{return ReaderLock;}
//ReentrantReadWriteLock$ReadLock
public static class ReadLock implements Lock {
 protected ReadLock(ReentrantReadwritLock lock) {
  sync = lock.sync;  //最后還是通過(guò)Sync內(nèi)部類(lèi)實(shí)現(xiàn)鎖
  }
 …… //它實(shí)現(xiàn)的是Lock接口,其余的實(shí)現(xiàn)可以和ReentrantLock作對(duì)比,獲取鎖、釋放鎖等等
}
//ReentrantReadWriteLock$WriteLock
public static class WriteLock implemnts Lock {
 protected WriteLock(ReentrantReadWriteLock lock) {
  sync = lock.sync;
  }
…… //它實(shí)現(xiàn)的是Lock接口,其余的實(shí)現(xiàn)可以和ReentrantLock作對(duì)比,獲取鎖、釋放鎖等等
}

上面是對(duì)ReentrantReadWriteLock做了一個(gè)大致的介紹,可以看到在其內(nèi)部有好幾個(gè)內(nèi)部類(lèi),實(shí)際上讀寫(xiě)鎖內(nèi)有兩個(gè)鎖——ReadLock、WriteLock,這兩個(gè)鎖都是實(shí)現(xiàn)自Lock接口,可以和ReentrantLock對(duì)比,而這兩個(gè)鎖的內(nèi)部實(shí)現(xiàn)則是通過(guò)Sync,也就是同步器AQS實(shí)現(xiàn)的,這也可以和ReentrantLock中的Sync對(duì)比。
  回顧一下AQS,其內(nèi)部有兩個(gè)重要的數(shù)據(jù)結(jié)構(gòu)——一個(gè)是同步隊(duì)列、一個(gè)則是同步狀態(tài),這個(gè)同步狀態(tài)應(yīng)用到讀寫(xiě)鎖中也就是讀寫(xiě)狀態(tài),但AQS中只有一個(gè)state整型來(lái)表示同步狀態(tài),讀寫(xiě)鎖中則有讀、寫(xiě)兩個(gè)同步狀態(tài)需要記錄。所以,讀寫(xiě)鎖將AQS中的state整型做了一下處理,它是一個(gè)int型變量一共4個(gè)字節(jié)32位,那么可以讀寫(xiě)狀態(tài)就可以各占16位——高16位表示讀,低16位表示寫(xiě)。

  

現(xiàn)在有一個(gè)疑問(wèn)如果state的值位5,二進(jìn)制為(00000000000000000000000000000101),如何快速確定讀和寫(xiě)各自的狀態(tài)呢?這就要用到位移運(yùn)算了。計(jì)算方式為:寫(xiě)狀態(tài)state & 0x0000FFFF,讀狀態(tài)state >>> 16。寫(xiě)狀態(tài)增加1等于state + 1,讀狀態(tài)增加1等于state + (1 << 16)。有關(guān)移位運(yùn)算可以參考《<<、>>、>>>移位操作》。

寫(xiě)鎖的獲取與釋放

根據(jù)我們之前的經(jīng)驗(yàn)可以得知:AQS已經(jīng)將獲取鎖的算法骨架搭好了,只需子類(lèi)實(shí)現(xiàn)tryAcquire(獨(dú)占鎖),故我們只需查看tryAcquire。

//ReentrantReadWriteLock$Sync
protected final boolean tryAcquire(int acquires) {
 Thread current = Thread.currentThread;
 int c = getState(); //獲取state狀態(tài)
 int w = exclusiveCount(c); //獲取寫(xiě)狀態(tài),即 state & 0x00001111
 if (c != 0) { //存在同步狀態(tài)(讀或?qū)懀飨乱徊脚袛?
  if (w == 0 || current != getExclusiveOwnerThread())  //寫(xiě)狀態(tài)為0,但同步狀態(tài)不為0表示有讀狀態(tài),此時(shí)獲取鎖失敗,或者當(dāng)前已經(jīng)有其他寫(xiě)線(xiàn)程獲取了鎖此時(shí)也獲取鎖失敗
   return false;
  if (w + exclusiveCount(acquire) > MAX_COUNT) //鎖重入是否超過(guò)限制
   throw new Error(“Maxium lock count exceeded”);
  setState(c + acquire); //記錄鎖狀態(tài)
  return true;
  }
  if (writerShouldBlock() || !compareAndSetState(c, c + acquires))
   return false;  //writerShouldBlock對(duì)于非公平鎖總是返回false,對(duì)于公平鎖則判斷同步隊(duì)列中是否有前驅(qū)節(jié)點(diǎn)
  setExclusiveOwnerThread(current);
  return true;
}

上面是寫(xiě)鎖的狀態(tài)獲取,不好理解的是writerShouldBlock方法,此方法上面有描述,非公平鎖直接返回false,而對(duì)于公平鎖則是調(diào)用hasQueuedPredecessors方法如下:

 //ReentrantReadWriteLock$FairSync
 final boolean writerShouldBlock() {
  return hasQueuedPredecessors();
 }

原因是為什么呢?這就要回到非公平鎖和公平鎖的區(qū)別上來(lái)了,簡(jiǎn)單回顧一下,詳情可參考《5.Lock接口及其實(shí)現(xiàn)ReentrantLock》。對(duì)于非公平鎖,每次線(xiàn)程獲取鎖時(shí)首先會(huì)強(qiáng)行進(jìn)行鎖獲取操作而不管同步隊(duì)列中是否有線(xiàn)程,當(dāng)獲取不到時(shí)才會(huì)將線(xiàn)程構(gòu)造至隊(duì)尾;對(duì)于公平鎖來(lái)講,只要同步隊(duì)列中存在線(xiàn)程,就不會(huì)去獲取鎖,而是將線(xiàn)程構(gòu)造添加至隊(duì)尾。所以重新回到寫(xiě)狀態(tài)的獲取上,tryAcquire方法里,前面發(fā)現(xiàn)沒(méi)有線(xiàn)程持有鎖,但是此時(shí)會(huì)根據(jù)鎖的不同做相應(yīng)操作,對(duì)于非公平鎖——搶鎖,對(duì)公平鎖——同步隊(duì)列中有線(xiàn)程,不搶鎖,添加至隊(duì)尾排隊(duì)。

寫(xiě)鎖的釋放與ReentrantLock的釋放過(guò)程基本類(lèi)似,畢竟都是獨(dú)占鎖,每次釋放減少寫(xiě)的狀態(tài),直到減小到0就表示寫(xiě)鎖已經(jīng)完全釋放。

讀鎖的獲取與釋放

同理,根據(jù)我們之前的經(jīng)驗(yàn)可以得知:AQS已經(jīng)將獲取鎖的算法骨架搭好了,只需子類(lèi)實(shí)現(xiàn)tryAcquireShared(共享鎖),故我們只需查看tryAcquireShared。我們知道對(duì)于共享模式下的鎖,它能夠被多個(gè)線(xiàn)程同時(shí)獲取,現(xiàn)在問(wèn)題來(lái)了,T1線(xiàn)程獲取了鎖,同步狀態(tài)state=1,此時(shí)T2也獲取了鎖,state=2,接著T1線(xiàn)程重入state=3,也就是說(shuō)讀狀態(tài)是所有線(xiàn)程讀鎖次數(shù)的總和,而每個(gè)線(xiàn)程各自獲取讀鎖的次數(shù)只能選擇保存在ThreadLock中,由線(xiàn)程自身維護(hù),所以在這個(gè)地方要做一些復(fù)雜處理,源碼有點(diǎn)長(zhǎng),但復(fù)雜就在于每個(gè)線(xiàn)程保存自身獲取讀鎖的次數(shù),具體參照源碼的tryAcquireShared,仔細(xì)閱讀并結(jié)合上面對(duì)寫(xiě)鎖獲取的分析不難讀懂。

讀鎖的釋放值得注意的地方在于自身維護(hù)的獲取鎖的次數(shù),以及通過(guò)移位操作減少狀態(tài)state – (1 << 16)。

以上這篇ReadWriteLock接口及其實(shí)現(xiàn)ReentrantReadWriteLock方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringCloud?@RefreshScope刷新機(jī)制淺析

    SpringCloud?@RefreshScope刷新機(jī)制淺析

    RefeshScope這個(gè)注解想必大家都用過(guò),在微服務(wù)配置中心的場(chǎng)景下經(jīng)常出現(xiàn),他可以用來(lái)刷新Bean中的屬性配置,那大家對(duì)他的實(shí)現(xiàn)原理了解嗎?它為什么可以做到動(dòng)態(tài)刷新呢
    2023-03-03
  • IDEA感覺(jué)不香了AI智能編程工具Cursor使用圖文教程

    IDEA感覺(jué)不香了AI智能編程工具Cursor使用圖文教程

    這篇文章主要介紹了IDEA感覺(jué)不香了AI智能編程工具Cursor使用,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • Mybatis Plus select 實(shí)現(xiàn)只查詢(xún)部分字段

    Mybatis Plus select 實(shí)現(xiàn)只查詢(xún)部分字段

    這篇文章主要介紹了Mybatis Plus select 實(shí)現(xiàn)只查詢(xún)部分字段的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java設(shè)計(jì)模式之責(zé)任鏈模式

    Java設(shè)計(jì)模式之責(zé)任鏈模式

    這篇文章介紹了Java設(shè)計(jì)模式之責(zé)任鏈模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Idea安裝Eslint插件提示:Plugin NativeScript was not installed的問(wèn)題

    Idea安裝Eslint插件提示:Plugin NativeScript was not installed的問(wèn)題

    這篇文章主要介紹了Idea安裝Eslint插件提示:Plugin NativeScript was not installed的問(wèn)題,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • 詳解Spring Kafka中關(guān)于Kafka的配置參數(shù)

    詳解Spring Kafka中關(guān)于Kafka的配置參數(shù)

    這篇文章主要介紹了詳解Spring Kafka中關(guān)于Kafka的配置參數(shù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Java集合TreeSet用法詳解

    Java集合TreeSet用法詳解

    本文詳細(xì)講解了Java集合TreeSet用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • Java連接MYSQL數(shù)據(jù)庫(kù)的詳細(xì)步驟

    Java連接MYSQL數(shù)據(jù)庫(kù)的詳細(xì)步驟

    這篇文章主要為大家介紹了Java連接MYSQL數(shù)據(jù)庫(kù)的詳細(xì)步驟,感興趣的小伙伴們可以參考一下
    2016-05-05
  • 如何徹底刪除SVN中的文件和文件夾(附恢復(fù)方法)

    如何徹底刪除SVN中的文件和文件夾(附恢復(fù)方法)

    在SVN中如果刪除某個(gè)文件或文件夾也可以在歷史記錄中進(jìn)行找回,有的時(shí)候需要徹底刪除某些文件,即不希望通過(guò)歷史記錄進(jìn)行恢復(fù),需要在服務(wù)器上對(duì)SVN的數(shù)據(jù)進(jìn)行重新整理
    2014-08-08
  • Java自然排序Comparable使用方法解析

    Java自然排序Comparable使用方法解析

    這篇文章主要介紹了Java自然排序Comparable使用方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04

最新評(píng)論

黔西| 闻喜县| 德钦县| 启东市| 开江县| 阿荣旗| 中西区| 保山市| 吉水县| 扬州市| 长宁县| 文水县| 乡城县| 肃宁县| 吉首市| 黔西| 枣阳市| 土默特左旗| 达日县| 东明县| 普兰县| 双辽市| 息烽县| 巴青县| 高台县| 白河县| 贡山| 镇沅| 革吉县| 大方县| 登封市| 青浦区| 凌海市| 岗巴县| 双峰县| 二手房| 长白| 霍邱县| SHOW| 田阳县| 昌图县|