国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

J.U.C|可重入鎖ReentrantLock

wangdai / 3487人閱讀

摘要:二什么是重入鎖可重入鎖,顧名思義,支持重新進(jìn)入的鎖,其表示該鎖能支持一個(gè)線程對(duì)資源的重復(fù)加鎖。將由最近成功獲得鎖,并且還沒(méi)有釋放該鎖的線程所擁有。可以使用和方法來(lái)檢查此情況是否發(fā)生。

一、寫(xiě)在前面

前幾篇我們具體的聊了AQS原理以及底層源碼的實(shí)現(xiàn),具體參見(jiàn)
《J.U.C|一文搞懂AQS》
《J.U.C|同步隊(duì)列(CLH)》
《J.U.C|AQS獨(dú)占式源碼分析》
《J.U.C|AQS共享式源碼分析》

本章我們來(lái)聊一聊其實(shí)現(xiàn)之一 可重入鎖ReentrantLock的實(shí)現(xiàn)原理以及源碼分析。

:本章主要講解非公平鎖的實(shí)現(xiàn)流程和源碼解析,其中涉及到AQS底層的實(shí)現(xiàn)因在前面幾章都已經(jīng)詳細(xì)聊過(guò)在這會(huì)一筆帶過(guò)。

二、什么是重入鎖

可重入鎖 ReentrantLock ,顧名思義,支持重新進(jìn)入的鎖,其表示該鎖能支持一個(gè)線程對(duì)資源的重復(fù)加鎖。

Java API 描述

一個(gè)可重入的互斥鎖 Lock,它具有與使用 synchronized 方法和語(yǔ)句所訪問(wèn)的隱式監(jiān)視器鎖相同的一些基本行為和語(yǔ)義,但功能更強(qiáng)大。

ReentrantLock 將由最近成功獲得鎖,并且還沒(méi)有釋放該鎖的線程所擁有。當(dāng)鎖沒(méi)有被另一個(gè)線程所擁有時(shí),調(diào)用 lock 的線程將成功獲取該鎖并返回。如果當(dāng)前線程已經(jīng)擁有該鎖,此方法將立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法來(lái)檢查此情況是否發(fā)生。

ReentrantLock還提供了公平鎖和非公平鎖的選擇, 其構(gòu)造方法接受一個(gè)公平參數(shù)(默認(rèn)是非公平方式),當(dāng)傳入ture時(shí)表示公平鎖, 否則為非公平鎖。其兩者的主要區(qū)別在于公平鎖獲取鎖是有順序的。但是其效率往往沒(méi)有非公平鎖的效率高,在多線程的訪問(wèn)時(shí)往往表現(xiàn)很低的吞吐量(即速度慢,常常急慢)。

來(lái)張圖緩解下

三、源碼分析

我們先來(lái)看一段代碼

ReentrantLock lock = new ReentrantLock();
        try {
            lock.lock();
            // 業(yè)務(wù)代碼
        } finally {
            lock.unlock();
        }

這一段代碼相信學(xué)過(guò)Java的同學(xué)都非常熟悉了,今天我們就以此為入口一步一步的帶你深入其底層世界。

共享狀態(tài)的獲取(鎖的獲取)
lock()方法
// ReentrantLock --> lokc() 實(shí)現(xiàn)Lock 接口的方法
public void lock() {
        // 調(diào)用內(nèi)部類sync 的lock方法, 這里有兩種實(shí)現(xiàn),公平鎖(FairSync)非公平鎖(NonfairSync)這里我們來(lái)主要說(shuō) NonfairSync
        sync.lock();
    }

ReentrantLock 的lock 方法, sync 為ReentrantLock的一個(gè)內(nèi)部類,其繼承了AbstractQueuedSynchronizer(AQS), 他有兩個(gè)子類公平鎖FairSync 和非公平鎖NonfairSync

ReentrantLock 中其中大部分的功能的實(shí)現(xiàn)都是委托給內(nèi)部類Sync實(shí)現(xiàn)的,在Sync 中定義了abstract void lock() 留給子類去實(shí)現(xiàn), 默認(rèn)實(shí)現(xiàn)了final boolean nonfairTryAcquire(int acquires) 方法,可以看出其為非公平鎖默認(rèn)實(shí)現(xiàn)方式,下面我講下給看下非公平鎖lock方法。

NonfairSync.lock()
// ReentrantLock$NonfairSync
final void lock() {
    if (compareAndSetState(0, 1))
        // 非公平原則, 上來(lái)就插隊(duì)來(lái)嘗試下獲取共享狀態(tài),如果成功則設(shè)置當(dāng)前持有鎖線程為自己,獲取鎖成功。
        setExclusiveOwnerThread(Thread.currentThread());
    else
        //如果失敗則調(diào)用AQS中的acquire方法
        acquire(1);
}

首先就嘗試獲取同步狀態(tài)(體現(xiàn)非公平鎖上來(lái)就插隊(duì))如果成功則將持有鎖線程設(shè)置為自己,失敗則走AQS中的acquire方法。

AQS.acquire(int arg)
// AQS中的acquire方法,在AQS中已經(jīng)講過(guò),首先會(huì)調(diào)用tryAcquire(arg)方法,tryAcquire(arg)方法會(huì)有具體由子類去實(shí)現(xiàn)。
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

這里AQS中的源碼我就不再過(guò)多的講解了(無(wú)非就是嘗試獲取同步狀態(tài)成功直接返回,失敗加入同步隊(duì)列等待被喚醒),主要來(lái)將留給子類實(shí)現(xiàn)的tryAcquire(arg)方法。
如有對(duì)AQS不明白的請(qǐng)看文章頭中列出的幾篇文章過(guò)一下或者鎖搜引擎中鎖搜下。

Nonfairync.tryAcquire(int acquires)
protected final boolean tryAcquire(int acquires) {
            // 非公平鎖的tryAcquire(arg)實(shí)現(xiàn),委托給Sync.nonfairTryAcquire(int acquires)具體處理
            return nonfairTryAcquire(acquires);
        }

ReentrantLock中非公平鎖tryAcquire(int acquires)的實(shí)現(xiàn),具體調(diào)用其父類Sync中默認(rèn)實(shí)現(xiàn)的(上面已經(jīng)提過(guò))。

Sync.nonfairTryAcquire(int acquires)
final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            // 獲取共享狀態(tài)
            int c = getState();
            if (c == 0) {
                // 如果共享狀態(tài)為0,說(shuō)明鎖空閑,利用CAS來(lái)獲取鎖(將共享狀態(tài)值改為1)
                if (compareAndSetState(0, acquires)) {
                    // 如果設(shè)置成功,則表明獲取鎖成功,將持有鎖線程設(shè)置為自己
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 如果c != 0 則說(shuō)明鎖已經(jīng)被線程持有,判斷持有鎖的線程是不是自己(這里就是可重入鎖的具體體現(xiàn))
            else if (current == getExclusiveOwnerThread()) {
                // 如果當(dāng)前持有鎖的線程是自己,說(shuō)明可重入,將共享狀態(tài)值加1,返回ture
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

主要邏輯:

首先判斷同步狀態(tài) state == 0 ?,

如果state == 0 則說(shuō)明該鎖處于空閑狀態(tài),直接通過(guò)CAS設(shè)置同步狀態(tài),成功將持有鎖線程設(shè)置為自己返回ture,

如果state !=0 判斷鎖的持有者是否是自己,是則說(shuō)明可重入將state 值加1 返回ture,

否則返回false.

來(lái)張圖加深下理解

:此圖只是體現(xiàn)了RenntrantLock中的狀態(tài),其中涉及到AQS中的狀態(tài)流轉(zhuǎn)沒(méi)有在這體現(xiàn)。

鎖的釋放

鎖的釋放邏輯就比較簡(jiǎn)單

ReentrantLock.unlock()
public void unlock() {
        sync.release(1);
    }

同樣在ReentrantLock.unlock()方法中將具體釋放邏輯委托給了內(nèi)部類Sync來(lái)實(shí)現(xiàn), 在這Sync 同樣沒(méi)有去實(shí)現(xiàn)release(1)而是使用其父類AQS的默認(rèn)實(shí)現(xiàn)。

AQS.release(1)
// 調(diào)用AQS中的release 方法
public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

AQS釋放鎖的邏輯比較簡(jiǎn)單,同樣就不解釋了(無(wú)非就是釋放鎖,喚醒后繼節(jié)點(diǎn))具體來(lái)看下需要自類實(shí)現(xiàn)的tryRelease(arg) 釋放共享狀態(tài)的方法。

Sync.tryRelease(int releases)
protected final boolean tryRelease(int releases) {
            // 共享狀態(tài)值減去releases
            int c = getState() - releases;
            // 如果持有鎖的線程線程不是自己,則拋出異常(很好理解不能把別人的鎖釋放了)
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            // 共享狀態(tài) state = 0 則表明釋放鎖成功
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

釋放共享狀態(tài)(鎖)的邏輯比較簡(jiǎn)單,主要是將共享狀態(tài)的值減去releases,減后共享狀態(tài)值為0表示釋放鎖成功將持有鎖線程設(shè)置為null 返回 ture。

四、總結(jié)

最后我們來(lái)對(duì)ReentrantLock加鎖和釋放鎖做個(gè)簡(jiǎn)單總結(jié),ReentrantLock 是一個(gè)可重入鎖提供了兩種實(shí)現(xiàn)方式公平鎖非公平鎖
非公平鎖獲取鎖流程:
1: 首先不管三七二一就來(lái)個(gè) CAS 嘗試獲取鎖。
2: 成功則皆大歡喜。
3: 失敗,再次獲取下共享狀態(tài)(萬(wàn)一這會(huì)有人釋放了尼)判斷是否為0
4: 如果為0 則說(shuō)明鎖空閑,再次CAS獲取鎖成功將持有鎖線程設(shè)置為自己并返回ture
5:不為0,判斷持有者是否是自己、是自己表明可重入state + 1 返回ture 否則返回false(就去同步隊(duì)列中排隊(duì)去)。

非公平鎖釋放鎖流程
很簡(jiǎn)單state - 1 = 0 則釋放成功否則失敗。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/74316.html

相關(guān)文章

  • J.U.C|一文搞懂AQS

    摘要:接著線程過(guò)來(lái)通過(guò)方式獲取鎖,獲取鎖的過(guò)程就是通過(guò)操作變量將其值從變?yōu)椤>€程加鎖成功后還有一步重要的操作,就是將設(shè)置成為自己。線程屁顛屁顛的就去等待區(qū)小憩一會(huì)去了。 一、寫(xiě)在前面 這篇文章,我們聊一聊Java并發(fā)中的核武器, AQS底層實(shí)現(xiàn)。 不管是工作三四年、還是五六年的在工作或者面試中涉及到并發(fā)的是時(shí)候總是繞不過(guò)AQS這個(gè)詞。 首先,確實(shí)還有很多人連AQS是什么都不知道,甚至有的竟...

    tommego 評(píng)論0 收藏0
  • [JDK源碼]J.U.C-AQS-ReentrantLock

    摘要:公平鎖阻塞隊(duì)列前邊有線程,要去后邊排隊(duì),簡(jiǎn)單來(lái)說(shuō)滾后邊等著去。非公平鎖不管是否有線程排隊(duì),先槍鎖基于實(shí)現(xiàn)的可重入鎖實(shí)現(xiàn)類。 AQS原理介紹: AQS (Abstra...

    不知名網(wǎng)友 評(píng)論0 收藏0
  • J.U.C|讀-寫(xiě)鎖ReentrantReadWriteLock

    摘要:所以就有了讀寫(xiě)鎖。只要沒(méi)有,讀取鎖可以由多個(gè)線程同時(shí)保持。其讀寫(xiě)鎖為兩個(gè)內(nèi)部類都實(shí)現(xiàn)了接口。讀寫(xiě)鎖同樣依賴自定義同步器來(lái)實(shí)現(xiàn)同步狀態(tài)的,而讀寫(xiě)狀態(tài)就是其自定義同步器的狀態(tài)。判斷申請(qǐng)寫(xiě)鎖數(shù)量是否超標(biāo)超標(biāo)則直接異常,反之則設(shè)置共享狀態(tài)。 一、寫(xiě)在前面 在上篇我們聊到了可重入鎖(排它鎖)ReentrantLcok ,具體參見(jiàn)《J.U.C|可重入鎖ReentrantLock》 Reentra...

    Tonny 評(píng)論0 收藏0
  • J.U.C|讀-寫(xiě)鎖ReentrantReadWriteLock

    摘要:所以就有了讀寫(xiě)鎖。只要沒(méi)有,讀取鎖可以由多個(gè)線程同時(shí)保持。其讀寫(xiě)鎖為兩個(gè)內(nèi)部類都實(shí)現(xiàn)了接口。讀寫(xiě)鎖同樣依賴自定義同步器來(lái)實(shí)現(xiàn)同步狀態(tài)的,而讀寫(xiě)狀態(tài)就是其自定義同步器的狀態(tài)。判斷申請(qǐng)寫(xiě)鎖數(shù)量是否超標(biāo)超標(biāo)則直接異常,反之則設(shè)置共享狀態(tài)。 一、寫(xiě)在前面 在上篇我們聊到了可重入鎖(排它鎖)ReentrantLcok ,具體參見(jiàn)《J.U.C|可重入鎖ReentrantLock》 Reentra...

    wendux 評(píng)論0 收藏0
  • Java 重入鎖 ReentrantLock 原理分析

    摘要:的主要功能和關(guān)鍵字一致,均是用于多線程的同步。而僅支持通過(guò)查詢當(dāng)前線程是否持有鎖。由于和使用的是同一把可重入鎖,所以線程可以進(jìn)入方法,并再次獲得鎖,而不會(huì)被阻塞住。公平與非公平公平與非公平指的是線程獲取鎖的方式。 1.簡(jiǎn)介 可重入鎖ReentrantLock自 JDK 1.5 被引入,功能上與synchronized關(guān)鍵字類似。所謂的可重入是指,線程可對(duì)同一把鎖進(jìn)行重復(fù)加鎖,而不會(huì)被阻...

    lx1036 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<