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

Java多線程并發(fā)之ReentrantLock

 更新時(shí)間:2023年04月26日 11:50:46   作者:JayChou_Code  
這篇文章主要介紹了Java?多線程并發(fā)ReentrantLock,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下

ReentrantLock

公平鎖和非公平鎖

這個(gè)類(lèi)是接口 Lock的實(shí)現(xiàn)類(lèi),也是悲觀鎖的一種,但是它提供了 lockunlock方法用于主動(dòng)進(jìn)行鎖的加和拆。在之前使用的 sychronized關(guān)鍵字是隱式加鎖機(jī)制,而它是顯示加鎖,同時(shí),這個(gè)類(lèi)的構(gòu)造方法提供了公平和非公平的兩種機(jī)制。

什么是公平和非公平呢?就是多線程對(duì)共享資源進(jìn)行爭(zhēng)奪的時(shí)候,會(huì)出現(xiàn)一個(gè)線程或幾個(gè)線程完全占有共享資源,使得某些線程在長(zhǎng)時(shí)間處于等待狀態(tài)。公平就是要等待時(shí)間過(guò)長(zhǎng)的線程先獲得鎖。

而在 ReentrantLock類(lèi)中,提供了公平鎖和非公平鎖的使用。

ReentrantLock源碼中,構(gòu)造器提供了一個(gè)參數(shù)入口,

public ReentrantLock(boolean fair) {
	sync = fair ? new FairSync() : new NonfairSync();
}

當(dāng)fair為true的時(shí)候,會(huì)創(chuàng)造一個(gè) FairSync對(duì)象給 sync屬性,FairSync是繼承自 Sync的類(lèi),其中有一個(gè) Lock方法,而在 ReentrantLock的Lcok中使用的是 sync屬性的 Lock方法,故能夠保證“公平”。

使用非公平鎖就不需要在構(gòu)造器中傳參數(shù)。

在使用的時(shí)候,需要手動(dòng)上鎖和解鎖。

使用公平鎖,會(huì)將占優(yōu)勢(shì)的線程進(jìn)行限制,恢復(fù)掛起的線程,但是這個(gè)過(guò)程在CPU層面來(lái)講,是存在明顯時(shí)間差異的,非公平鎖的執(zhí)行效率相對(duì)更高,所以一般來(lái)說(shuō)不建議使用公平鎖,除非現(xiàn)實(shí)業(yè)務(wù)上需要符合實(shí)際需求。

重入鎖

ReentrantLock本身還支持重入的功能。

重入鎖(Reentrant Lock)是一種支持重入的獨(dú)占鎖,它允許線程多次獲取同一個(gè)鎖,在釋放鎖之前必須相應(yīng)地多次釋放鎖。重入鎖通常由兩個(gè)操作組成:上鎖(lock)和解鎖(unlock)。當(dāng)一個(gè)線程獲取了重入鎖后,可以再次獲取該鎖而不被阻塞,同時(shí)必須通過(guò)相同數(shù)量的解鎖操作來(lái)釋放鎖。

重入鎖具有如下特點(diǎn):

  • 重入性:重入鎖允許同一個(gè)線程多次獲取同一把鎖,避免了死鎖的發(fā)生。
  • 獨(dú)占性:與公平鎖和非公平鎖一樣,重入鎖也是一種獨(dú)占鎖,同一時(shí)刻只能有一個(gè)線程持有該鎖。
  • 可中斷性:重入鎖支持在等待鎖的過(guò)程中中斷該線程的執(zhí)行。
  • 條件變量:在使用 java.util.concurrent.locks.Condition 類(lèi)配合重入鎖實(shí)現(xiàn)等待/通知機(jī)制時(shí),等待狀態(tài)總是與重入鎖相關(guān)聯(lián)的。

重入鎖相對(duì)于 synchronized 關(guān)鍵字的優(yōu)勢(shì)在于,重入鎖具有更高的靈活性和擴(kuò)展性,支持公平鎖和非公平鎖、可中斷鎖和可輪詢鎖等特性,能夠更好地滿足多線程環(huán)境下的并發(fā)控制需要。synchroized也有重入性。

ReentrantLock lock = new ReentrantLock(true);
public void get(){
    while(true){
        try{
            lock.lock();
            lock.lock();
        }catch(Exception exception){

        }finally{
            lock.unlock();
            lock.unlock();
        }
    }
}

可重入的前提 lock是同一個(gè)對(duì)象,而關(guān)鍵字 synchroized的 Monitor也是同一個(gè)對(duì)象充當(dāng),才能判定為重入。

public void get(){
    while(true){
        synchronized(this){
            System.out.println("外層");
            synchronized(this){
                System.out.println("內(nèi)層");
            }
        }
    }
}

那么Java是怎么檢測(cè)鎖的重入和獲取鎖的次數(shù)的呢?在之前說(shuō)過(guò)的 ObjectMobitor的C++源代碼中有 _recursions和_count來(lái)記錄鎖的重入次數(shù)和線程獲取鎖的次數(shù)。這樣在Java層面就表示一個(gè)鎖對(duì)象都擁有一個(gè)鎖計(jì)數(shù)器 _count和一個(gè)指向持有這個(gè)鎖的線程的指針 _owner,只有當(dāng)前持有鎖的線程才能使得計(jì)數(shù)器+1,其他線程只有等待鎖被釋放(計(jì)數(shù)器置0)才能持有并+1。

在源碼中,非公平鎖的lock方法如下:

//ReentrantLock類(lèi)中:
final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}
//0的參數(shù)為是expect,是期望值,而1是update,是更新值

在執(zhí)行comparaAndSetState方法的時(shí)候,它會(huì)詢問(wèn)鎖的計(jì)數(shù)器(在底層執(zhí)行compareAndSwapInt的本地方法),并期望數(shù)值為0,如果為0返回true,然后設(shè)置執(zhí)行線程主是當(dāng)前線程。如果非0,那么他就會(huì)執(zhí)行acquire

//AbstractQueuedSynchronizer類(lèi)中:
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
//這里的tryAcquire,需要在其繼承的子類(lèi)中進(jìn)一步實(shí)現(xiàn)對(duì)應(yīng)的功能
//子類(lèi)可以根據(jù)自己的需要重新定義tryAcquire(int arg)的實(shí)現(xiàn)方式,從而實(shí)現(xiàn)更優(yōu)秀的鎖控制方案:
//而在其子類(lèi)FairSync中便覆蓋了這個(gè)方法
protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}

將線程放入等待隊(duì)列。

同時(shí)計(jì)數(shù)器是通過(guò) unlock來(lái)-1,所以 lock和unlock次數(shù)不匹配就會(huì)產(chǎn)生死鎖,也就是當(dāng)兩個(gè)線程調(diào)用同一個(gè) ReentrantLock如果一個(gè)線程中的上鎖解鎖次數(shù)不相等,那么計(jì)數(shù)器沒(méi)有被清零,當(dāng)另一個(gè)線程請(qǐng)求鎖的時(shí)候,看到鎖計(jì)數(shù)器不是0,就認(rèn)為被的線程仍然持有它,所以一直等待它被釋放。需要了解底層的可以去看AQS中的release方法。

而在 ReentrantLock中有一個(gè)抽象內(nèi)部類(lèi) Sync,它繼承自抽象類(lèi)AbstractQueuedSynchronizer(簡(jiǎn)稱AQS),這個(gè)類(lèi)中有一個(gè)內(nèi)部 Node類(lèi),當(dāng)有線程等待這把鎖的時(shí)候,會(huì)創(chuàng)建一個(gè)等待隊(duì)列,放置這些處于等待的線程。(AQS實(shí)現(xiàn)比較復(fù)雜,有興趣可以看看“竹子愛(ài)熊貓”大佬的文章。)

小結(jié)

ReentrantLock類(lèi)中,有內(nèi)部類(lèi)三個(gè),Sync,FairSync,NonfairSync,他們的關(guān)系是Sync是后兩個(gè)的父類(lèi),后兩個(gè)是兄弟類(lèi),同時(shí)Sync繼承自AQS類(lèi),在AQS中有很多實(shí)現(xiàn)公平和非公平、可重入的機(jī)制,而具體實(shí)現(xiàn)效果的是Sync,FairSync,NonfairSync。

疑惑

在下列代碼中,為什么在第一個(gè)線程的最后加上.join(),沒(méi)有使得線程阻塞,而沒(méi)有它就會(huì)阻塞?

Lock lock = new ReentrantLock();
new CompletableFuture().runAsync(() -> {
    lock.lock();
    try{
        System.out.println(1);
        TimeUnit.SECONDS.sleep(2);
    }catch(Exception e){
    }finally{
}});
//上面加上.join()
new CompletableFuture().runAsync(() -> {
    lock.lock();
    try{
        System.out.println(2);
    }catch(Exception e){
    }finally{
        lock.unlock();
}}).join();

到此這篇關(guān)于Java多線程并發(fā)之ReentrantLock的文章就介紹到這了,更多相關(guān)ava  ReentrantLock內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis3.4.6 批量更新 foreach 遍歷map 的正確姿勢(shì)詳解

    mybatis3.4.6 批量更新 foreach 遍歷map 的正確姿勢(shì)詳解

    這篇文章主要介紹了mybatis3.4.6 批量更新 foreach 遍歷map 的正確姿勢(shì)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • 學(xué)習(xí)Java中Class類(lèi)及其用法

    學(xué)習(xí)Java中Class類(lèi)及其用法

    這篇文章分為三大部分,主要內(nèi)容有Class類(lèi)原理詳解、用法及泛化,需要的朋友可以參考下
    2015-07-07
  • Spring?boot?啟動(dòng)流程及外部化配置方法

    Spring?boot?啟動(dòng)流程及外部化配置方法

    平時(shí)我們開(kāi)發(fā)Spring boot 項(xiàng)目的時(shí)候,一個(gè)SpringBootApplication注解加一個(gè)main方法就可以啟動(dòng)服務(wù)器運(yùn)行起來(lái),那它到底是怎么運(yùn)行起來(lái)的呢?這篇文章主要介紹了Spring?boot?啟動(dòng)流程及外部化配置,需要的朋友可以參考下
    2022-12-12
  • Java編寫(xiě)擲骰子游戲

    Java編寫(xiě)擲骰子游戲

    這篇文章主要介紹了Java編寫(xiě)擲骰子游戲,需要的朋友可以參考下
    2015-11-11
  • Java驗(yàn)證碼圖片生成代碼

    Java驗(yàn)證碼圖片生成代碼

    這篇文章主要為大家詳細(xì)介紹了Java驗(yàn)證碼圖片生成代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • JAVA提高第八篇 動(dòng)態(tài)代理技術(shù)

    JAVA提高第八篇 動(dòng)態(tài)代理技術(shù)

    這篇文章主要為大家詳細(xì)介紹了JAVA動(dòng)態(tài)代理技術(shù)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 詳解Java運(yùn)算中的取余

    詳解Java運(yùn)算中的取余

    這篇文章主要介紹了java運(yùn)算中的取余,在java運(yùn)算中,取余符號(hào)是?%,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • Springboot中的@Order如何使用

    Springboot中的@Order如何使用

    本文主要介紹了Springboot中的@Order如何使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • JavaEE在線人數(shù)管理系統(tǒng)

    JavaEE在線人數(shù)管理系統(tǒng)

    這篇文章主要為大家分享了JavaEE在線人數(shù)管理系統(tǒng),顯示在線人數(shù)、在線人詳細(xì)信息、管理員踢人等功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java中\(zhòng)n和\r區(qū)別

    Java中\(zhòng)n和\r區(qū)別

    本文主要介紹了Java中\(zhòng)n和\r區(qū)別。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02

最新評(píng)論

开封县| 南充市| 新建县| 海丰县| 芒康县| 大关县| 始兴县| 颍上县| 乌审旗| 恩平市| 武强县| 广丰县| 澄城县| 建始县| 神农架林区| 炎陵县| 大渡口区| 香港 | 容城县| 宣武区| 南靖县| 巴塘县| 石阡县| 来宾市| 瓮安县| 宜城市| 海阳市| 滕州市| 鹿泉市| 轮台县| 从江县| 延津县| 湖口县| 佛教| 昭苏县| 景洪市| 通许县| 青铜峡市| 澄江县| 寿阳县| 老河口市|