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

Java并發(fā)編程ReentrantReadWriteLock加讀鎖流程

 更新時(shí)間:2023年05月10日 11:10:42   作者:bright丶  
這篇文章主要介紹了Java并發(fā)編程ReentrantReadWriteLock加讀鎖流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

protected final int tryAcquireShared(int unused) {
    Thread current = Thread.currentThread();
    int c = getState();
    if (exclusiveCount(c) != 0 &&
        getExclusiveOwnerThread() != current)
        return -1;
    int r = sharedCount(c);
    if (!readerShouldBlock() &&
        r < MAX_COUNT &&
        compareAndSetState(c, c + SHARED_UNIT)) {
        if (r == 0) {
            firstReader = current;
            firstReaderHoldCount = 1;
        } else if (firstReader == current) {
            firstReaderHoldCount++;
        } else {
            HoldCounter rh = cachedHoldCounter;
            if (rh == null || rh.tid != getThreadId(current))
                cachedHoldCounter = rh = readHolds.get();
            else if (rh.count == 0)
                readHolds.set(rh);
            rh.count++;
        }
        return 1;
    }
    return fullTryAcquireShared(current);
}

上面是嘗試加讀鎖流程的代碼,既然這篇是番外篇,那就不按正常流程一點(diǎn)一點(diǎn)去分析了,著重拿出一部分來(lái)分析一下。ReentrantReadWriteLockReentrantLock相比,除了多了讀寫(xiě)鎖之外,還增加了很多屬性,比如firstReaderfirstReaderHoldCount、cachedHoldCounter......那我們這篇文章就介紹一下這些新屬性的含義以及上面代碼中加鎖成功后的處理。

屬性介紹

static final class HoldCounter {
    int count = 0;
    final long tid = getThreadId(Thread.currentThread());
}

HoldCount類型用來(lái)存儲(chǔ)線程ID和線程持有的讀鎖數(shù)量

private transient ThreadLocalHoldCounter readHolds;
static final class ThreadLocalHoldCounter
    extends ThreadLocal&lt;HoldCounter&gt; {
    public HoldCounter initialValue() {
        return new HoldCounter();
    }
}

readHolds通過(guò)ThreadLocal在線程本地存儲(chǔ)了一個(gè)HoldCounter對(duì)象,表示當(dāng)前線程持有的讀鎖重入數(shù)量,主要是為了方便在發(fā)生重入或者釋放鎖時(shí),分別計(jì)算每個(gè)線程持有的讀鎖數(shù)量。

private transient HoldCounter cachedHoldCounter;

cachedHoldCounter存儲(chǔ)的是最后一個(gè)獲取讀鎖成功的線程持有的讀鎖數(shù)量。但是如果只有一個(gè)線程獲取讀鎖,會(huì)使用firstReaderfirstReaderHoldCount來(lái)記錄線程持有讀鎖數(shù)量,只有獲取讀鎖的線程數(shù)大于1時(shí)才會(huì)用cachedHoldCounter存儲(chǔ)最后線程持有的讀鎖數(shù)量。

private transient Thread firstReader = null;

第一個(gè)獲取讀鎖的線程,確切地說(shuō)是把讀鎖數(shù)量從0改成1的線程,并且當(dāng)前還沒(méi)有釋放鎖。如果第一個(gè)線程釋放了鎖,就會(huì)把firstReader設(shè)為null,只有當(dāng)所有讀鎖釋放之后,下一個(gè)獲取讀鎖成功的線程就成為firstReader。

private transient int firstReaderHoldCount;

第一個(gè)獲取讀鎖的線程持有讀鎖的數(shù)量。

加鎖成功處理

int r = sharedCount(c);
if (r == 0) {
    firstReader = current;
    firstReaderHoldCount = 1;
} else if (firstReader == current) {
    firstReaderHoldCount++;
} else {
    HoldCounter rh = cachedHoldCounter;
    if (rh == null || rh.tid != getThreadId(current))
        cachedHoldCounter = rh = readHolds.get();
    else if (rh.count == 0)
        readHolds.set(rh);
    rh.count++;
}

這里截取加鎖成功之后處理的代碼來(lái)分析下對(duì)這些屬性的操作。

  • if (r == 0)表示共享鎖數(shù)量為0,當(dāng)前線程就是第一個(gè)獲取讀鎖成功的線程,所以firstReaderfirstReaderHoldCount記錄的就是當(dāng)前線程。
  • 如果讀鎖數(shù)量不是0,但是當(dāng)前線程是第一個(gè)線程,那就直接在原來(lái)數(shù)量基礎(chǔ)上進(jìn)行累加 firstReaderHoldCount++;
  • 如果讀鎖數(shù)量不為0,而且當(dāng)前線程也不是第一個(gè)線程,這時(shí)就需要用到cachedHoldCounter了。
    • rh == null表示當(dāng)前線程是第二個(gè)線程,rh.tid != getThreadId(current)表示當(dāng)前線程至少是第三個(gè)線程(這里不考慮重入情況,只考慮當(dāng)前線程第一次獲取讀鎖成功),兩個(gè)條件合起來(lái)可以理解為之前緩存的最后一個(gè)獲取讀鎖成功的線程不是當(dāng)前線程,所以就需要更新為當(dāng)前線程cachedHoldCounter = rh = readHolds.get()。
    • 如果之前緩存的最后一個(gè)線程是當(dāng)前線程,那么就會(huì)有一個(gè)特殊情況rh.count == 0,這里可以理解為一個(gè)線程釋放了讀鎖之后又重新獲取了讀鎖,釋放完所有鎖時(shí),為了防止內(nèi)存泄漏會(huì)調(diào)用readHolds.remove()清除線程本地存儲(chǔ)的信息,而現(xiàn)在加鎖成功了就需要在線程本地重新記錄持有鎖的數(shù)量,既然緩存的就是當(dāng)前線程的,那就直接用緩存來(lái)更新到線程本地就可以了。

以上就是Java并發(fā)編程ReentrantReadWriteLock番外的詳細(xì)內(nèi)容,更多關(guān)于Java并發(fā)ReentrantReadWriteLock的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

尼木县| 江陵县| 武义县| 宁津县| 吉林市| 额济纳旗| 东台市| 抚顺县| 基隆市| 出国| 耒阳市| 渝中区| 榕江县| 牙克石市| 盐亭县| 济源市| 长垣县| 小金县| 云和县| 比如县| 什邡市| 小金县| 武城县| 吉木萨尔县| 莱州市| 衡阳县| 津南区| 漳浦县| 岫岩| 莱西市| 红原县| 搜索| 宜昌市| 肇东市| 湾仔区| 抚宁县| 桐乡市| 濮阳县| 宿州市| 休宁县| 清丰县|