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

一篇文章讓你徹底了解Java可重入鎖和不可重入鎖

 更新時(shí)間:2021年06月01日 17:08:43   作者:Loser_Keep.  
最近正在閱讀Java ReentrantLock源碼,始終對(duì)可重入和不可重入概念理解不透徹,今天特地整理了本篇文章,讓你徹底了解Java可重入鎖和不可重入鎖,需要的朋友可以參考下

可重入鎖 

廣義上的可重入鎖指的是可重復(fù)可遞歸調(diào)用的鎖,在外層使用鎖之后,在內(nèi)層仍然可以使用,并且不發(fā)生死鎖(前提得是同一個(gè)對(duì)象或者class),這樣的鎖就叫做可重入鎖。

我的理解就是,某個(gè)線程已經(jīng)獲得某個(gè)鎖,可以無(wú)需等待而再次獲取鎖,并且不會(huì)出現(xiàn)死鎖(不同線程當(dāng)然不能多次獲得鎖,需要等待)。

簡(jiǎn)單的說(shuō),就是某個(gè)線程獲得某個(gè)鎖,之后可以不用等待而再次獲取鎖且不會(huì)出現(xiàn)死鎖。

常見的可重入鎖

Synchronized和ReentrantLock 都是可重入鎖。

可重入鎖的釋放

同一個(gè)線程獲取同一個(gè)鎖,狀態(tài)值state會(huì)累加,假設(shè)state累加到了2,每釋放一次鎖會(huì)減1,只有當(dāng)狀態(tài)值state減到0了,其他線程才有機(jī)會(huì)獲取鎖。也就是說(shuō),state歸零才是已釋放鎖的標(biāo)致。

可重入鎖示例

public class ReentrantTest implements Runnable {
 
    @Override
    public void run() {
        get();
    }
 
    public synchronized void get() {
        System.out.println(Thread.currentThread().getName());
        set();
    }
 
    /**
     * 遞歸方法
     */
    public synchronized void set() {
        System.out.println(Thread.currentThread().getName());
    }
 
    /**
     * 這里的對(duì)象鎖只有一個(gè),就是rt對(duì)象的鎖。
     * 當(dāng)執(zhí)行rt的get方法時(shí),該線程獲得rt對(duì)象的鎖。在get方法內(nèi)執(zhí)行set方法時(shí)再次請(qǐng)求rt對(duì)象的鎖,因?yàn)閟ynchronized是可重入鎖,所以又可以得到該鎖。循環(huán)這個(gè)過(guò)程。
     * 假設(shè)不是可重入鎖的話,那么請(qǐng)求的過(guò)程中會(huì)出現(xiàn)阻塞,從而導(dǎo)致死鎖。
     * @param args
     */
    public static void main(String[] args) {
        ReentrantTest rt = new ReentrantTest();
        // for(;;)模擬無(wú)限循環(huán)
        for(;;){
            new Thread(rt).start();
        }
    }
}

分析:這里的對(duì)象鎖只有一個(gè),就是rt對(duì)象的鎖。當(dāng)執(zhí)行rt的get方法時(shí),該線程獲得rt對(duì)象的鎖。在get方法內(nèi)執(zhí)行set方法時(shí)再次請(qǐng)求rt對(duì)象的鎖,因?yàn)閟ynchronized是可重入鎖,所以又可以得到該鎖。循環(huán)這個(gè)過(guò)程。假設(shè)不是可重入鎖的話,那么請(qǐng)求的過(guò)程中會(huì)出現(xiàn)阻塞,從而導(dǎo)致死鎖。

死鎖

多線程中,不同的線程都在等待其它線程釋放鎖,而其它線程由于一些原因遲遲沒(méi)有釋放鎖。程序的運(yùn)行處于阻塞狀態(tài),不能正常運(yùn)行也不能正常終止。

運(yùn)行結(jié)果

set()和get()同時(shí)輸出了相同的線程名稱,也就是說(shuō)某個(gè)線程執(zhí)行的時(shí)候,不僅進(jìn)入了set同步方法,還進(jìn)入了get同步方法。遞歸使用synchronized也沒(méi)有發(fā)生死鎖,證明其是可重入的。

可重入鎖的實(shí)現(xiàn)原理?

每一個(gè)鎖關(guān)聯(lián)一個(gè)線程持有者和計(jì)數(shù)器,當(dāng)計(jì)數(shù)器為 0 時(shí)表示該鎖沒(méi)有被任何線程持有,那么任何線程都可能獲得該鎖而調(diào)用相應(yīng)的方法;當(dāng)某一線程請(qǐng)求成功后,JVM會(huì)記下鎖的持有線程,并且將計(jì)數(shù)器置為 1;此時(shí)其它線程請(qǐng)求該鎖,則必須等待;而該持有鎖的線程如果再次請(qǐng)求這個(gè)鎖,就可以再次拿到這個(gè)鎖,同時(shí)計(jì)數(shù)器會(huì)遞增1;當(dāng)線程退出同步代碼塊時(shí),計(jì)數(shù)器會(huì)遞減1,如果計(jì)數(shù)器為 0,則釋放該鎖。

再分析一下上面可重入鎖的例子

遞歸調(diào)用一次同步代碼塊,計(jì)數(shù)器會(huì)變?yōu)?,整個(gè)遞歸調(diào)用執(zhí)行完,先退出內(nèi)層執(zhí)行減1,再退出外層執(zhí)行減1。然后釋放鎖。

不可重入鎖

就是某個(gè)線程已經(jīng)獲得某個(gè)鎖,之后不可以再次獲取鎖,會(huì)被阻塞。

設(shè)計(jì)一個(gè)不可重入鎖

public class Lock {
    private boolean isLocked = false;
    /**
     * 加鎖
     */
    public synchronized void lock() throws Exception{
        while(isLocked){
            //當(dāng)前線程釋放鎖,讓出CPU,進(jìn)入等待狀態(tài),直到被喚醒,才繼續(xù)執(zhí)行15行
            wait();
            System.out.println("wait");
        }
        isLocked = true;
    }
    /**
     * 解鎖
     */
    public synchronized void unlock(){
        isLocked = false;
        //喚醒一個(gè)等待的線程繼續(xù)執(zhí)行
        notify();
    }
}

測(cè)試

public class Test {
    Lock lock = new Lock();
    public void print() throws Exception{
        //加鎖 標(biāo)記為true
        lock.lock();
        //釋放鎖->等待 阻塞在16行
        doAdd();
        lock.unlock();
    }
    public void doAdd() throws Exception{
        lock.lock();
        System.out.println("doAdd");
        lock.unlock();
    }
 
    public static void main(String[] args)throws Exception {
        Test test=new Test();
        test.print();
    }
}

結(jié)果:這里,雖然模擬的是不可重入鎖,實(shí)際還是在單線程環(huán)境中的。當(dāng)前線程執(zhí)行print()方法首先加鎖 標(biāo)記為true,接下來(lái)釋放鎖->等待 阻塞在16行內(nèi)部的14行。整個(gè)過(guò)程中,第一次進(jìn)入lock同步方法,執(zhí)行完畢,第二次進(jìn)入lock同步方法,阻塞等待。這個(gè)例子很好的說(shuō)明了不可重入鎖。  

到此這篇關(guān)于一篇文章讓你徹底了解Java可重入鎖和不可重入鎖的文章就介紹到這了,更多相關(guān)Java可重入鎖和不可重入鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中的自定義FailureAnalyzer詳解

    SpringBoot中的自定義FailureAnalyzer詳解

    這篇文章主要介紹了SpringBoot中的自定義FailureAnalyzer詳解,FailureAnalyzer是一種很好的方式在啟動(dòng)時(shí)攔截異常并將其轉(zhuǎn)換為易讀的消息,并將其包含在FailureAnalysis中, Spring Boot為應(yīng)用程序上下文相關(guān)異常、JSR-303驗(yàn)證等提供了此類分析器,需要的朋友可以參考下
    2023-12-12
  • 解決Swagger2返回map復(fù)雜結(jié)構(gòu)不能解析的問(wèn)題

    解決Swagger2返回map復(fù)雜結(jié)構(gòu)不能解析的問(wèn)題

    這篇文章主要介紹了解決Swagger2返回map復(fù)雜結(jié)構(gòu)不能解析的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    Mybatis自身通過(guò)了逆向工程來(lái)幫助我們快速生成代碼,但Mybatis-plus卻更加強(qiáng)大,不僅僅可以生成dao,pojo,mapper,還有基本的controller和service層代碼,接下來(lái)我們來(lái)寫一個(gè)簡(jiǎn)單的人門案例是看看如何mybatis-plus是怎么實(shí)現(xiàn)的,需要的朋友可以參考下
    2021-06-06
  • Java基礎(chǔ)篇之反射機(jī)制示例詳解

    Java基礎(chǔ)篇之反射機(jī)制示例詳解

    反射是Java可以提供的一個(gè)靈活又強(qiáng)大的功能,使用Java反射,您可以知道這個(gè)類在運(yùn)行時(shí)具有什么屬性和方法,也可以修改屬性,調(diào)用方法,創(chuàng)建類的實(shí)例,這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)篇之反射機(jī)制的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • 詳解Java中==和equals()的區(qū)別

    詳解Java中==和equals()的區(qū)別

    這篇文章主要介紹了Java中==和equals()的區(qū)別,,==可以使用在基本數(shù)據(jù)類型變量和引用數(shù)據(jù)類型變量中,equals()是方法,只能用于引用數(shù)據(jù)類型,需要的朋友可以參考下
    2021-11-11
  • Spring導(dǎo)入properties配置文件代碼示例

    Spring導(dǎo)入properties配置文件代碼示例

    這篇文章主要介紹了Spring導(dǎo)入properties配置文件代碼示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • 詳解JavaEE中Apollo安裝使用小結(jié)

    詳解JavaEE中Apollo安裝使用小結(jié)

    這篇文章主要介紹了詳解JavaEE中Apollo安裝與使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • JSON 格式的弊端與解決方法(真實(shí)示例)

    JSON 格式的弊端與解決方法(真實(shí)示例)

    JSON 格式是目前最流行的數(shù)據(jù)交互格式,廣泛應(yīng)用于前后端分離的系統(tǒng)。但也有一些場(chǎng)合不適合使用 JSON 格式,這篇文章主要介紹了JSON 格式的弊端與解決方法,需要的朋友可以參考下
    2022-09-09
  • SpringBoot結(jié)合Redis實(shí)現(xiàn)緩存

    SpringBoot結(jié)合Redis實(shí)現(xiàn)緩存

    本文主要介紹了SpringBoot結(jié)合Redis實(shí)現(xiàn)緩存,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • java線程死鎖代碼示例

    java線程死鎖代碼示例

    這篇文章主要介紹了java線程死鎖代碼示例,分享了一個(gè)簡(jiǎn)單線程死鎖的例子,需要的朋友可以參考下。
    2017-11-11

最新評(píng)論

彝良县| 晋江市| 清徐县| 阜康市| 柯坪县| 漳州市| 马边| 静乐县| 商洛市| 贵定县| 图们市| 平凉市| 监利县| 满洲里市| 禄丰县| 延川县| 清徐县| 南漳县| 于都县| 大港区| 瑞昌市| 伊金霍洛旗| 沈丘县| 丘北县| 建德市| 远安县| 田阳县| 湖州市| 科技| 安吉县| 九龙坡区| 金平| 肇东市| 樟树市| 龙江县| 博兴县| 确山县| 鄄城县| 库尔勒市| 吉安县| 定陶县|