第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

鎖的可重入性驗(yàn)證

1. 前言

本節(jié)內(nèi)容主要是對(duì) Java 鎖的可重入性進(jìn)行驗(yàn)證,鎖的可重入性的設(shè)計(jì)是避免死鎖非常好的設(shè)計(jì)思想。本節(jié)內(nèi)容的知識(shí)點(diǎn)如下:

  • 什么是鎖的可重入性,這是本節(jié)課程的基礎(chǔ)內(nèi)容;
  • 了解可重入鎖與非可重入性鎖的不同之處,以凸顯可重入性鎖的優(yōu)勢(shì)所在,為本節(jié)基礎(chǔ)內(nèi)容;
  • 了解什么情況下使用可重入鎖,是本節(jié)的重點(diǎn)內(nèi)容之一;
  • synchronized 關(guān)鍵字驗(yàn)證鎖的可重入性試驗(yàn),為本節(jié)核心內(nèi)容之一;
  • ReentrantLock 驗(yàn)證鎖的可重入性試驗(yàn),為本節(jié)核心內(nèi)容之一;

其實(shí) synchronized 關(guān)鍵字與 ReentrantLock 都是 Java 常見(jiàn)的可重入鎖,本節(jié)內(nèi)容使用 ReentrantLock 和 synchronized 來(lái)講解鎖的可重入性。

2. 什么是鎖的可重入性

定義:可重入鎖又名遞歸鎖,是指在同一個(gè)線(xiàn)程在外層方法獲取鎖的時(shí)候,再進(jìn)入該線(xiàn)程的內(nèi)層方法會(huì)自動(dòng)獲取鎖(前提鎖對(duì)象得是同一個(gè)對(duì)象或者 class),不會(huì)因?yàn)橹耙呀?jīng)獲取過(guò)還沒(méi)釋放而阻塞。

Java 中 ReentrantLock 和 synchronized 都是可重入鎖,可重入鎖的一個(gè)優(yōu)點(diǎn)是可一定程度避免死鎖。

可重入鎖原理:可重入鎖的原理是在鎖內(nèi)部維護(hù)一個(gè)線(xiàn)程標(biāo)示,用來(lái)標(biāo)示該鎖目前被哪個(gè)線(xiàn)程占用,然后關(guān)聯(lián)一個(gè)計(jì)數(shù)器。一開(kāi)始計(jì)數(shù)器值為 0,說(shuō)明該鎖沒(méi)有被任何線(xiàn)程占用。當(dāng)一個(gè)線(xiàn)程獲取了該鎖時(shí),計(jì)數(shù)器的值會(huì)變成 1,這時(shí)其他線(xiàn)程再來(lái)獲取該鎖時(shí)會(huì)發(fā)現(xiàn)鎖的所有者不是自己而被阻塞掛起。

但是當(dāng)獲取了該鎖的線(xiàn)程再次獲取鎖時(shí)發(fā)現(xiàn)鎖擁有者是自己,就會(huì)把計(jì)數(shù)器值加+1, 當(dāng)釋放鎖后計(jì)數(shù)器值-1。當(dāng)計(jì)數(shù)器值為 0 時(shí),鎖里面的線(xiàn)程標(biāo)示被重置為 null,這時(shí)候被阻塞的線(xiàn)程會(huì)被喚醒來(lái)競(jìng)爭(zhēng)獲取該鎖。

3. 可重入鎖與非可重入性鎖

Java 中 ReentrantLock 和 synchronized 都是可重入鎖,可重入鎖的一個(gè)優(yōu)點(diǎn)是可一定程度避免死鎖。

為了解釋可重入鎖與非可重入性鎖的區(qū)別與聯(lián)系,我們拿可重入鎖 ReentrantLock 和 非重入鎖 NonReentrantLock 進(jìn)行簡(jiǎn)單的分析對(duì)比。

相同點(diǎn): ReentrantLock 和 NonReentrantLock 都繼承父類(lèi) AQS,其父類(lèi) AQS 中維護(hù)了一個(gè)同步狀態(tài) status 來(lái)計(jì)數(shù)重入次數(shù),status 初始值為 0。

不同點(diǎn):當(dāng)線(xiàn)程嘗試獲取鎖時(shí),可重入鎖先嘗試獲取并更新 status 值,如果 status == 0 表示沒(méi)有其他線(xiàn)程在執(zhí)行同步代碼,則把 status 置為 1,當(dāng)前線(xiàn)程開(kāi)始執(zhí)行。

如果 status != 0,則判斷當(dāng)前線(xiàn)程是否是獲取到這個(gè)鎖的線(xiàn)程,如果是的話(huà)執(zhí)行 status+1,且當(dāng)前線(xiàn)程可以再次獲取鎖。

而非可重入鎖是直接去獲取并嘗試更新當(dāng)前 status 的值,如果 status != 0 的話(huà)會(huì)導(dǎo)致其獲取鎖失敗,當(dāng)前線(xiàn)程阻塞,導(dǎo)致死鎖發(fā)生。

4. 什么情況下使用可重入鎖

我們先來(lái)看看如下代碼:同步方法 helloB 方法調(diào)用了同步方法 helloA。

public class DemoTest{
    public synchronized void helloA(){
        System.out.println("helloA");
    }
    public synchronized void helloB(){
        System.out.println("helloB");
        helloA();
    }
}

在如上代碼中,調(diào)用 helloB 方法前會(huì)先獲取內(nèi)置鎖,然后打印輸出。之后調(diào)用 helloA 方法,在調(diào)用前會(huì)先去獲取內(nèi)置鎖,如果內(nèi)置鎖不是可重入的,那么調(diào)用線(xiàn)程將會(huì)一直被阻塞。

因此,對(duì)于同步方法內(nèi)部調(diào)用另外一個(gè)同步方法的情況下,一定要使用可重入鎖,不然會(huì)導(dǎo)致死鎖的發(fā)生。

5. synchronized 驗(yàn)證鎖的可重入性

為了更好的理解 synchronized 驗(yàn)證鎖的可重入性,我們來(lái)設(shè)計(jì)一個(gè)簡(jiǎn)單的場(chǎng)景。

場(chǎng)景設(shè)計(jì)

  • 創(chuàng)建一個(gè)類(lèi),該類(lèi)中有兩個(gè)方法,helloA 方法和 helloB 方法;
  • 將兩個(gè)方法內(nèi)部的邏輯進(jìn)行 synchronized 同步;
  • helloA 方法內(nèi)部調(diào)用 helloB 方法,營(yíng)造可重入鎖的場(chǎng)景;
  • main 方法創(chuàng)建線(xiàn)程,調(diào)用 helloA 方法;
  • 觀察結(jié)果,看是否可以成功進(jìn)行調(diào)用。

實(shí)例

public class DemoTest {
    public static void main(String[] args) {
        new Thread(new SynchronizedTest()). start();
    }
}
class SynchronizedTest implements Runnable {
    private final Object obj = new Object();
    public void helloA() { //方法1,調(diào)用方法2
        synchronized (obj) {
            System.out.println(Thread.currentThread().getName() + " helloA()");
            helloB();
        }
    }
    public void helloB() {
        synchronized (obj) {
            System.out.println(Thread.currentThread().getName() + " helloB()");
        }
    }
    @Override
    public void run() {
        helloA(); //調(diào)用helloA方法
    }
}

結(jié)果驗(yàn)證

Thread-0 helloA()
Thread-0 helloB()

結(jié)果解析:如果同一線(xiàn)程,鎖不可重入的話(huà),helloB 需要等待 helloA 釋放 obj 鎖,如此一來(lái),helloB 無(wú)法進(jìn)行鎖的獲取,最終造成無(wú)限等待,無(wú)法正常執(zhí)行。此處說(shuō)明了 synchronized 關(guān)鍵字的可重入性,因此能夠正常進(jìn)行兩個(gè)方法的執(zhí)行。

6. ReentrantLock 驗(yàn)證鎖的可重入性

相同的場(chǎng)景,對(duì)代碼進(jìn)行如下改造,將 synchronized 同步代碼塊修改成 lock 接口同步,我們看代碼實(shí)例如下:

public class DemoTest {
    public static void main(String[] args) {
        new Thread(new SynchronizedTest()). start();
    }
}
class SynchronizedTest implements Runnable {
    private final Lock lock = new ReentrantLock();
    public void helloA() { //方法1,調(diào)用方法2
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " helloA()");
            helloB();
        } finally {
            lock.unlock();
        }
    }
    public void helloB() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " helloB()");
        } finally {
            lock.unlock();
        }
    }
    @Override
    public void run() {
        helloA();
    }
}

結(jié)果驗(yàn)證

Thread-0 helloA()
Thread-0 helloB()

結(jié)果解析:ReentrantLock 一樣是可重入鎖,試驗(yàn)成功。

7. 小結(jié)

鎖的可重入性這一概念對(duì)于并發(fā)編程非常重要,對(duì)于本節(jié)內(nèi)容需要深入的理解并掌握。我們之前已經(jīng)學(xué)習(xí)過(guò)了 synchronized 關(guān)鍵字和 ReentrantLock 鎖,此處知識(shí)用兩者進(jìn)行了可重入的驗(yàn)證。

本節(jié)關(guān)鍵點(diǎn)在于可重入性的意義所在,需要結(jié)合實(shí)例進(jìn)行更加細(xì)致的理解和掌握。