亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

可重入鎖 

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

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

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

常見的可重入鎖

Synchronized和ReentrantLock 都是可重入鎖。

可重入鎖的釋放

同一個線程獲取同一個鎖,狀態(tài)值state會累加,假設state累加到了2,每釋放一次鎖會減1,只有當狀態(tài)值state減到0了,其他線程才有機會獲取鎖。也就是說,state歸零才是已釋放鎖的標致。

可重入鎖示例

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());
    }
 
    /**
     * 這里的對象鎖只有一個,就是rt對象的鎖。
     * 當執(zhí)行rt的get方法時,該線程獲得rt對象的鎖。在get方法內(nèi)執(zhí)行set方法時再次請求rt對象的鎖,因為synchronized是可重入鎖,所以又可以得到該鎖。循環(huán)這個過程。
     * 假設不是可重入鎖的話,那么請求的過程中會出現(xiàn)阻塞,從而導致死鎖。
     * @param args
     */
    public static void main(String[] args) {
        ReentrantTest rt = new ReentrantTest();
        // for(;;)模擬無限循環(huán)
        for(;;){
            new Thread(rt).start();
        }
    }
}

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

死鎖

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

運行結(jié)果

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

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

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

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

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

不可重入鎖

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

設計一個不可重入鎖

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

測試

public class Test {
    Lock lock = new Lock();
    public void print() throws Exception{
        //加鎖 標記為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é)果:這里,雖然模擬的是不可重入鎖,實際還是在單線程環(huán)境中的。當前線程執(zhí)行print()方法首先加鎖 標記為true,接下來釋放鎖->等待 阻塞在16行內(nèi)部的14行。整個過程中,第一次進入lock同步方法,執(zhí)行完畢,第二次進入lock同步方法,阻塞等待。這個例子很好的說明了不可重入鎖。  

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

相關文章

  • Java中Switch的使用方法及新特性

    Java中Switch的使用方法及新特性

    在java中控制流程語句是由選擇語句、循環(huán)語句、跳轉(zhuǎn)語句構(gòu)成,選擇語句包括if和switch,在過多的使用if語句嵌套會使程序很難閱讀,這時就可以用到switch語句,這篇文章主要給大家介紹了關于Java中Switch的使用方法及新特性的相關資料,需要的朋友可以參考下
    2023-11-11
  • java生成指定范圍隨機數(shù)的多種代碼

    java生成指定范圍隨機數(shù)的多種代碼

    今天在寫代碼的時候需要用到一個生成指定范圍隨機數(shù)的函數(shù),百度了一下,發(fā)現(xiàn)了很多種方法,這里簡單為大家整理一下,方便需要的朋友
    2017-08-08
  • Spring解密之XML解析與Bean注冊示例詳解

    Spring解密之XML解析與Bean注冊示例詳解

    這篇文章主要給大家介紹了關于Spring解密之XML解析與Bean注冊的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面小編來一起學習學習吧。
    2018-01-01
  • 詳解Spring Data JPA系列之投影(Projection)的用法

    詳解Spring Data JPA系列之投影(Projection)的用法

    本篇文章主要介紹了詳解Spring Data JPA系列之投影(Projection)的用法,具有一定的參考價值,有興趣的可以了解一下
    2017-07-07
  • Jenkins發(fā)送測試報告郵件過程詳解

    Jenkins發(fā)送測試報告郵件過程詳解

    這篇文章主要介紹了Jenkins發(fā)送測試報告郵件過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • Java 程序設計總復習題(java基礎代碼)

    Java 程序設計總復習題(java基礎代碼)

    這篇文章主要介紹了Java 程序設計總復習題,主要是java基礎代碼,方便學習java的同學
    2021-05-05
  • java 靜態(tài)工廠代替多參構(gòu)造器的適用情況與優(yōu)劣

    java 靜態(tài)工廠代替多參構(gòu)造器的適用情況與優(yōu)劣

    這篇文章主要介紹了java 靜態(tài)工廠代替多參構(gòu)造器的優(yōu)劣,幫助大家更好的理解和使用靜態(tài)工廠方法,感興趣的朋友可以了解下
    2020-12-12
  • 詳解Java中StringBuffer類常用方法

    詳解Java中StringBuffer類常用方法

    這篇文章主要為大家介紹了java中StringBuffer類常用方法
    2016-01-01
  • 一文帶你了解Java中的函數(shù)式編程

    一文帶你了解Java中的函數(shù)式編程

    函數(shù)式編程的理論基礎是阿隆佐·丘奇(Alonzo Church)于 1930 年代提出的 λ 演算(Lambda Calculus)。這篇文章主要為大家介紹了函數(shù)式編程的相關知識,希望對大家有所幫助
    2023-04-04
  • java遞歸處理單位人員組織機構(gòu)樹方式

    java遞歸處理單位人員組織機構(gòu)樹方式

    這篇文章主要介紹了java遞歸處理單位人員組織機構(gòu)樹方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評論