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

Java并發(fā)編程Lock?Condition和ReentrantLock基本原理

 更新時(shí)間:2023年09月15日 11:41:31   作者:福  
這篇文章主要介紹了Java并發(fā)編程Lock?Condition和ReentrantLock基本原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Lock框架

Lock框架為java并發(fā)編程提供了除synchronized之外的另外一種選擇。synchronized是隱式實(shí)現(xiàn),底層封裝了對(duì)鎖資源的獲取和釋放的所有實(shí)現(xiàn)細(xì)節(jié),程序員不需要關(guān)心也沒有辦法關(guān)心這些細(xì)節(jié),使用起來非常方便也非常安全。

而Lock由java語言實(shí)現(xiàn),公開了鎖資源獲取和釋放的所有細(xì)節(jié),在資源鎖定過程中提供了更多選項(xiàng),在獲取鎖資源后,可以通過Condition對(duì)象對(duì)鎖資源做細(xì)粒度的管理。

最關(guān)鍵的是Lock大量使用了CAS,充分利用“持有鎖的線程不會(huì)長時(shí)間占用鎖”這一假設(shè),有可能的情況下就盡量先自旋、后鎖定資源。所以多線程環(huán)境下Lock應(yīng)該比synchronized有更好的性能。

java線程池框架Executor中大量使用了基于Lock接口的ReentrantLock,掌握ReentrantLock是深入理解各種Executor(ThreadPoolExecutor、ScheduledThreadPoolExecutor等)以及各種阻塞隊(duì)列的必要前提。

Lock有獨(dú)占鎖、共享鎖的區(qū)別,獨(dú)占鎖是指某一線程獲取鎖資源后即獨(dú)占該鎖資源、其他線程只能等待,共享鎖是指多個(gè)線程能同時(shí)獲得鎖資源。

今天我們的研究對(duì)象是ReentrantLock,ReentrantLock是獨(dú)占鎖,主要研究內(nèi)容:

  • ReentrantLock的基本概念
  • 基礎(chǔ)數(shù)據(jù)機(jī)構(gòu):AQS,CLH隊(duì)列
  • 公平鎖、非公平鎖
  • Condition
  • 沒有Condition參與的lock、unlock
  • 有Condition參與的lock、unlock

ReentrantLock的基本概念

顧名思義,ReentrantLock是“可重入鎖”,意思是同一線程可以多次獲得鎖,n次獲得需要n次釋放才能最終釋放掉ReentrantLock。

ReentrantLock的基本原理:

  • 與synchronized不同,ReentrantLock不存在“鎖對(duì)象”的概念,或者可以理解為鎖對(duì)象就是ReentrantLock對(duì)象本身
  • ReentrantLock設(shè)置一個(gè)狀態(tài)值,通過對(duì)狀態(tài)值的原子操作實(shí)現(xiàn)對(duì)鎖資源的獲取和釋放,任何一個(gè)線程能獲取鎖資源的充分必要條件是ReentrantLock處于空閑狀態(tài),同理,任何一個(gè)線程獲得鎖資源后ReentrantLock即處于占用狀態(tài)
  • ReentrantLock的兩個(gè)最基本的操作:lock和unlock,lock獲取鎖資源,unlock釋放鎖資源
  • ReentrantLock維護(hù)一個(gè)CLH隊(duì)列,CLH隊(duì)列是一個(gè)先進(jìn)先出的雙向隊(duì)列
  • ReentrantLock處于空閑狀態(tài)則lock調(diào)用立即返回,調(diào)用線程獲得鎖資源。否則,請求線程進(jìn)入CLH隊(duì)列排隊(duì),等待被其他線程喚醒
  • 獲得鎖資源的線程在業(yè)務(wù)執(zhí)行完成后調(diào)用unlock釋放鎖資源,之后以FIFO的原則喚醒最先進(jìn)入隊(duì)列排隊(duì)的線程
  • 被喚醒的線程繼續(xù)執(zhí)行l(wèi)ock操作,節(jié)點(diǎn)從CLH隊(duì)列出隊(duì),返回---意味著請求鎖資源的線程在等待后獲取鎖資源成功,繼續(xù)第6步的邏輯

以上是沒有Condition對(duì)象參與的ReentrantLock的獲取、釋放鎖資源的邏輯,相對(duì)比較簡單。

有Condition參與的時(shí)候,情況會(huì)稍微復(fù)雜一點(diǎn):

  • ReentrantLock對(duì)象可以通過new Condition()操作持有Condition對(duì)象,一個(gè)ReentrantLock可以持有多個(gè)Condition對(duì)象
  • Condition維護(hù)一個(gè)Condition隊(duì)列
  • Condition的常用的操作包括await、signal等,執(zhí)行操作的時(shí)候假設(shè)當(dāng)前線程已經(jīng)獲取到了ReentrantLock鎖資源
  • await操作會(huì)釋放掉當(dāng)前線程已經(jīng)獲取到的ReentrantLock鎖資源、掛起當(dāng)前線程,并且將當(dāng)前線程加入Condition的隊(duì)列排隊(duì)等待被其他線程喚醒。比如DelayedWorkQueue的take方法中,如果當(dāng)前DelayedWorkQueue隊(duì)列空的話,則take線程加入到命名為available的Condition中排隊(duì)等候
  • 當(dāng)相關(guān)操作可能導(dǎo)致Condition的條件滿足的時(shí)候,調(diào)用Condition的signal方法喚醒在Condition隊(duì)列中等待的線程。比如上例中DelayedWorkQueue的add方法完成之后,調(diào)用available的signal方法,喚醒在available隊(duì)列中排隊(duì)等候的線程。
  • 線程被喚醒之后從Condition隊(duì)列出隊(duì),進(jìn)ReentrantLock的CLH隊(duì)列排隊(duì)等待重新獲取鎖資源

Condition舉例:take方法中隊(duì)列空的話,掛起等待

Condition舉例:offer方法中寫入隊(duì)列后,喚醒等待的線程

對(duì)ReentrantLock應(yīng)該有一個(gè)基本的認(rèn)識(shí)了,如果只是想要對(duì)ReentrantLock做一個(gè)基本了解、能夠看懂ReentrantLock的應(yīng)用、而不是要從源碼角度做深入研究的話,個(gè)人認(rèn)為掌握上面這些基本原理應(yīng)該就夠了,保證能看懂阻塞隊(duì)列、線程池中的有關(guān)ReentrantLock的源碼邏輯了。

但是如果想要徹底搞清楚ReentrantLock到底是怎么實(shí)現(xiàn)以上邏輯的,就需要從源碼角度繼續(xù)做深入研究了。

ReentrantLock數(shù)據(jù)結(jié)構(gòu):AQS及CLH隊(duì)列

多個(gè)線程同時(shí)競爭ReentrantLock鎖資源的時(shí)候,只能有一個(gè)競爭獲勝的線程獲得鎖資源、其他線程就只能排隊(duì)等待。這個(gè)用來排隊(duì)的隊(duì)列就是CLH隊(duì)列,AQS(AbstractQueuedSynchronizer)是實(shí)現(xiàn)CLH隊(duì)列的虛擬類。

ReentrantLock有一個(gè)非常重要的屬性Sync,Sync是AQS的虛擬擴(kuò)展類,Sync有兩個(gè)實(shí)現(xiàn)類:NonfairSync和FairSync,類結(jié)構(gòu)如下:

NonfairSync和FairSync都是AQS的最終實(shí)現(xiàn),AQS虛擬類是一個(gè)標(biāo)準(zhǔn)模板,定義了Lock鎖的基本數(shù)據(jù)結(jié)構(gòu)(阻塞隊(duì)列)、并實(shí)現(xiàn)了Lock的絕大部分功能。

進(jìn)入隊(duì)列排隊(duì)的線程被封裝為Node,Node是AQS定義的內(nèi)部類,是我們學(xué)習(xí)AQS首先要掌握的內(nèi)容。

Node的重要屬性:

waitStatus:等待狀態(tài),Node就是用來排隊(duì)的,waitStatus就代表當(dāng)前節(jié)點(diǎn)的等待狀態(tài),有以下幾種等待狀態(tài):

  • CANCELLED = 1:表示當(dāng)前等待線程已經(jīng)被calcel掉了
  • SIGNAL = -1:表示該節(jié)點(diǎn)是在CLH隊(duì)列中排隊(duì)等待出隊(duì)
  • CONDITION = -2:表示當(dāng)前節(jié)點(diǎn)是在Condition隊(duì)列中等待出隊(duì)
  • PROPAGATE = -3:共享鎖會(huì)用到,暫不分析

prev:上一節(jié)點(diǎn)
next:雙向隊(duì)列嘛,當(dāng)然也要有下一節(jié)點(diǎn)
Thread thread:節(jié)點(diǎn)的主角,排隊(duì)線程
nextWaiter:Condition隊(duì)列專用,用來指向Condition隊(duì)列的下一節(jié)點(diǎn)

AQS的同步隊(duì)列(CLH)以及Condition隊(duì)列的節(jié)點(diǎn)都是用這個(gè)Node,所以Node類做了一部分針對(duì)兩者的兼容設(shè)計(jì),比如nextWaiter是針對(duì)Condtion隊(duì)列的下一節(jié)點(diǎn),next是針對(duì)CLH的下一節(jié)點(diǎn)。

AQS重要屬性

state:鎖狀態(tài),通過對(duì)state的原子操作實(shí)現(xiàn)對(duì)鎖資源的控制:某一線程通過原子操作成功將state從空閑修改為占用則意味著當(dāng)前線程成功獲得了鎖資源。無法獲得鎖資源的線程則封裝為Node節(jié)點(diǎn)進(jìn)入隊(duì)列排隊(duì)等待。

head:首節(jié)點(diǎn),頭節(jié)點(diǎn)
tail:尾結(jié)點(diǎn)

通過head節(jié)點(diǎn)、tail節(jié)點(diǎn),以及每個(gè)節(jié)點(diǎn)的prev、next,AQS實(shí)現(xiàn)了一個(gè)雙向隊(duì)列。

公平鎖和非公平鎖

所謂的公平鎖和非公平鎖就是由Sync屬性決定的:當(dāng)Sync創(chuàng)建為NonfairSync的時(shí)候,就是非公平的ReentrantLock,否則就是公平的ReentrantLock。

使用無參構(gòu)造器創(chuàng)建的是非公平ReentrantLock,有參構(gòu)造器ReentrantLock(boolean fair)可以通過參數(shù)指定創(chuàng)建公平還是非公平鎖。

公平鎖在線程請求鎖資源的時(shí)候會(huì)檢查CLH隊(duì)列,隊(duì)列不空的話首先進(jìn)入隊(duì)列排隊(duì),先提出申請的線程會(huì)優(yōu)先獲得鎖資源,因此是“公平”的鎖。

非公平鎖在線程請求鎖資源的時(shí)候不會(huì)檢查CLH隊(duì)列,直接嘗試獲得鎖資源,獲取失敗后才進(jìn)入隊(duì)列排隊(duì)。所以請求線程會(huì)得到比隊(duì)列中的線程更高的優(yōu)先級(jí),對(duì)于隊(duì)列中排隊(duì)的線程來說是不公平的,所以叫非公平鎖。

Condition

Condition提供await和signal(以及他們的變種)方法為ReentrantLock鎖資源提供更多選擇:當(dāng)前線程獲取到ReentrantLock鎖資源后,可以通過Condition對(duì)象的await方法掛起當(dāng)前線程直到其他線程通過該對(duì)象的signal方法喚醒。

一個(gè)ReentrantLock可以創(chuàng)建多個(gè)Condition對(duì)象,每一個(gè)Condition對(duì)象都是獨(dú)立的、互不影響。ReentrantLock好比是一條街上的黑社會(huì)老大,黑社會(huì)老大首先要把這條街拿下,也就是獲得ReentrantLock鎖資源。之后的每一個(gè)Condition好比是這條街道上的飯店A、小賣店B、公共衛(wèi)生間C,分別對(duì)應(yīng)ConditionObjectA、ConditionObjectB、ConditionObjectC,得到黑社會(huì)老大允許后你就可以隨意進(jìn)出飯店吃飯了,但是如果飯店客滿了,就必須通過調(diào)用ConditionObjectA的await方法進(jìn)入到ConditionObjectA的隊(duì)列中排隊(duì)等待(當(dāng)前線程封裝為AQS中的Node進(jìn)入隊(duì)列(假設(shè)叫NodeA),當(dāng)前線程A掛起),此時(shí)黑社會(huì)老大需要交出對(duì)整條街的鎖權(quán)限(貌似不太合理...),此后飯店A有人吃完了要離店,就會(huì)通過ConditionObjectA的signal方法通知正在隊(duì)列中排隊(duì)等候的NodeA,于是NodeA從ConditionObjectA隊(duì)列中出來,到ReentrantLock的CLH隊(duì)列中排隊(duì)、等待重新獲取ReentrantLock鎖資源之后再喚醒線程A。這個(gè)過程中如果有其他人(其他線程)要進(jìn)入小賣店B,需要進(jìn)行操作的就是小賣店對(duì)應(yīng)的ConditionObjectB,和飯店對(duì)應(yīng)的ConditionObjectA沒有任何關(guān)系。

小結(jié)

發(fā)現(xiàn)開篇定下的內(nèi)容太多了,篇幅所限,后面的“沒有Condition參與的lock、unlock”以及“有Condition參與的lock、unlock”,基本就是上述邏輯的源碼分析,放在下一篇。

以上就是Java并發(fā)編程Lock Condition和ReentrantLock基本原理的詳細(xì)內(nèi)容,更多關(guān)于Java并發(fā)編程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Mybatis select記錄封裝的實(shí)現(xiàn)

    Mybatis select記錄封裝的實(shí)現(xiàn)

    這篇文章主要介紹了Mybatis select記錄封裝的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java concurrency集合之ConcurrentSkipListMap_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java concurrency集合之ConcurrentSkipListMap_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了Java concurrency集合之ConcurrentSkipListMap的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Python單元測試_使用裝飾器實(shí)現(xiàn)測試跳過和預(yù)期故障的方法

    Python單元測試_使用裝飾器實(shí)現(xiàn)測試跳過和預(yù)期故障的方法

    下面小編就為大家?guī)硪黄狿ython單元測試_使用裝飾器實(shí)現(xiàn)測試跳過和預(yù)期故障的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • 詳解Java Slipped Conditions

    詳解Java Slipped Conditions

    這篇文章主要介紹了Java Slipped Conditions的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-01-01
  • Java MD5加密(實(shí)例講解)

    Java MD5加密(實(shí)例講解)

    下面小編就為大家?guī)硪黄狫ava MD5加密(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • SpringCloud+Nacos多服務(wù)多實(shí)例本地測試過程

    SpringCloud+Nacos多服務(wù)多實(shí)例本地測試過程

    文章介紹了如何使用Nacos進(jìn)行服務(wù)注冊與發(fā)現(xiàn),通過配置和啟動(dòng)不同實(shí)例來實(shí)現(xiàn)服務(wù)的高可用性,并展示了如何在前端調(diào)用服務(wù)接口,確保系統(tǒng)的穩(wěn)定運(yùn)行
    2026-02-02
  • 關(guān)于Mybatis的mapper接口函數(shù)重載問題

    關(guān)于Mybatis的mapper接口函數(shù)重載問題

    這篇文章主要介紹了關(guān)于Mybatis的mapper接口函數(shù)重載問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 深入講解Java Maven配置

    深入講解Java Maven配置

    這篇文章主要介紹了Maven的安裝配置詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • Java中map和flatMap的區(qū)別舉例詳解

    Java中map和flatMap的區(qū)別舉例詳解

    這篇文章主要給大家介紹了關(guān)于Java中map和flatMap區(qū)別的相關(guān)資料,在Java中Stream接口有map()和flatmap()方法,兩者都有中間流操作,并返回另一個(gè)流作為方法輸出,需要的朋友可以參考下
    2023-10-10
  • 基于hashmap 的擴(kuò)容和樹形化全面分析

    基于hashmap 的擴(kuò)容和樹形化全面分析

    這篇文章主要介紹了hashmap 的擴(kuò)容和樹形化的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評(píng)論

沈阳市| 东光县| 鹰潭市| 永吉县| 阳城县| 海口市| 永清县| 开鲁县| 宝坻区| 金溪县| 阳新县| 丁青县| 凤翔县| 含山县| 荣成市| 金沙县| 沅江市| 乐清市| 临朐县| 垣曲县| 三原县| 前郭尔| 宝鸡市| 东台市| 保靖县| 沂源县| 康保县| 修武县| 泰顺县| 江安县| 晋城| 安远县| 尤溪县| 司法| 平潭县| 邻水| 常德市| 日喀则市| 齐齐哈尔市| 读书| 梨树县|