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

Redisson之lock()和tryLock()的區(qū)別及說(shuō)明

 更新時(shí)間:2023年12月07日 10:02:43   作者:金鱗踏雨  
這篇文章主要介紹了Redisson之lock()和tryLock()的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

lock()和tryLock()的區(qū)別和原理解析

在Redisson中 lock() 方法 與 tryLock() 方法是有區(qū)別的!

我們先來(lái)闡述兩者的區(qū)別,再分析它們的源碼。

lock() 與 tryLock() 的區(qū)別

(1)返回值: lock() 是沒(méi)有返回值的;tryLock() 的返回值是 boolean。

(2)時(shí)機(jī):lock() 一直等鎖釋放;tryLock() 獲取到鎖返回true,獲取不到鎖并直接返回false。

(3)tryLock() 是可以被打斷的,被中斷的;lock是不可以。

tryLock()

@Override
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
    // 轉(zhuǎn)成毫秒,后面都是以毫秒為單位
    long time = unit.toMillis(waitTime);
    // 當(dāng)前時(shí)間
    long current = System.currentTimeMillis();
    // 線程ID-線程標(biāo)識(shí)
    long threadId = Thread.currentThread().getId();
 
    // 嘗試獲取鎖 tryAcquire() !!!
    Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
        
    // 如果上面嘗試獲取鎖返回的是null,表示成功;如果返回的是時(shí)間則表示失敗。
    if (ttl == null) {
        return true;
    }
 
    // 剩余等待時(shí)間 = 最大等待時(shí)間 -(用現(xiàn)在時(shí)間 - 獲取鎖前的時(shí)間)
    time -= System.currentTimeMillis() - current;
 
    // 剩余等待時(shí)間 < 0 失敗
    if (time <= 0) {
        acquireFailed(waitTime, unit, threadId);
        return false;
    }
 
    // 再次獲取當(dāng)前時(shí)間
    current = System.currentTimeMillis();
    // 重試邏輯,但不是簡(jiǎn)單的直接重試!
    // subscribe是訂閱的意思
    RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
    // 如果在剩余等待時(shí)間內(nèi),收到了釋放鎖那邊發(fā)過(guò)來(lái)的publish,則才會(huì)再次嘗試獲取鎖
    if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {
        if (!subscribeFuture.cancel(false)) {
            subscribeFuture.onComplete((res, e) -> {
                if (e == null) {   
                    // 取消訂閱
                    unsubscribe(subscribeFuture, threadId);
                }
            });
        }
        // 獲取鎖失敗
        acquireFailed(waitTime, unit, threadId);
        return false;
    }
 
    try {
        // 又重新計(jì)算了一下,上述的等待時(shí)間
        time -= System.currentTimeMillis() - current;
        if (time <= 0) {
            acquireFailed(waitTime, unit, threadId);
            return false;
        }
 
        // 重試!
        while (true) {
            long currentTime = System.currentTimeMillis();
            ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
 
            // 成功
            if (ttl == null) {
                return true;
            }
            
            // 又獲取鎖失敗,再次計(jì)算上面的耗時(shí)
            time -= System.currentTimeMillis() - currentTime;
            if (time <= 0) {
                acquireFailed(waitTime, unit, threadId);
                return false;
            }
 
            currentTime = System.currentTimeMillis();
            // 采用信號(hào)量的方式重試!
            if (ttl >= 0 && ttl < time) {
                subscribeFuture.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
            } else {
                subscribeFuture.getNow().getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
            }
            
            // 重新計(jì)算時(shí)間(充足就繼續(xù)循環(huán))
            time -= System.currentTimeMillis() - currentTime;
            if (time <= 0) {
                acquireFailed(waitTime, unit, threadId);
                return false;
            }
        }
    } finally {
        unsubscribe(subscribeFuture, threadId);
    }
}

lock()

private void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws InterruptedException {
 
	// 獲取當(dāng)前線程 ID
    long threadId = Thread.currentThread().getId();
    // 獲取鎖,正常獲取鎖則ttl為null,競(jìng)爭(zhēng)鎖時(shí)返回鎖的過(guò)期時(shí)間
    Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
    if (ttl == null) {
        return;
    }
		
    // 訂閱鎖釋放事件
    // 如果當(dāng)前線程通過(guò) Redis 的 channel 訂閱鎖的釋放事件獲取得知已經(jīng)被釋放,則會(huì)發(fā)消息通知待等待的線程進(jìn)行競(jìng)爭(zhēng)
    RFuture<RedissonLockEntry> future = subscribe(threadId);
    if (interruptibly) {
        commandExecutor.syncSubscriptionInterrupted(future);
    } else {
        commandExecutor.syncSubscription(future);
    }
 
    try {
        while (true) {
            // 循環(huán)重試獲取鎖,直至重新獲取鎖成功才跳出循環(huán)
            // 此種做法阻塞進(jìn)程,一直處于等待鎖手動(dòng)釋放或者超時(shí)才繼續(xù)線程    
            ttl = tryAcquire(-1, leaseTime, unit, threadId);
            if (ttl == null) {
                break;
            }
 
            if (ttl >= 0) {
                try {
                    future.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    if (interruptibly) {
                        throw e;
                    }
                    future.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
                }
            } else {
                if (interruptibly) {
                    future.getNow().getLatch().acquire();
                } else {
                    future.getNow().getLatch().acquireUninterruptibly();
                }
            }
        }
    } finally {
        // 最后釋放訂閱事件
        unsubscribe(future, threadId);
    }
}

建議應(yīng)盡量使用tryLock(),且攜帶參數(shù),因?yàn)榭稍O(shè)置最大等待時(shí)間以及可及時(shí)獲取加鎖返回值,后續(xù)可做一些其他加鎖失敗的業(yè)務(wù)。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Redis如何實(shí)現(xiàn)分布式鎖

    Redis如何實(shí)現(xiàn)分布式鎖

    相信大家對(duì)鎖已經(jīng)不陌生了,本文主要介紹了Redis如何實(shí)現(xiàn)分布式鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • redis中使用bloomfilter的白名單功能解決緩存穿透問(wèn)題

    redis中使用bloomfilter的白名單功能解決緩存穿透問(wèn)題

    本文主要介紹了redis中使用bloomfilter的白名單功能解決緩存穿透問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Redis數(shù)據(jù)編碼詳解

    Redis數(shù)據(jù)編碼詳解

    這篇文章主要介紹了Redis數(shù)據(jù)編碼的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2026-03-03
  • Redis中緩存和數(shù)據(jù)庫(kù)雙寫(xiě)數(shù)據(jù)不一致的原因及解決方案

    Redis中緩存和數(shù)據(jù)庫(kù)雙寫(xiě)數(shù)據(jù)不一致的原因及解決方案

    這篇文章主要介紹了Redis中緩存和數(shù)據(jù)庫(kù)雙寫(xiě)數(shù)據(jù)不一致的原因及解決方案,文中通過(guò)圖文結(jié)合的方式講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • Redis實(shí)現(xiàn)分布式事務(wù)的示例

    Redis實(shí)現(xiàn)分布式事務(wù)的示例

    Redis雖不支持傳統(tǒng)SQL數(shù)據(jù)庫(kù)ACID特性的事務(wù),但提供了事務(wù)特性,允許多命令捆綁執(zhí)行,通過(guò)命令MULTI、EXEC、DISCARD、WATCH實(shí)現(xiàn),感興趣的可以了解一下
    2024-10-10
  • Redis客戶端連接遠(yuǎn)程Redis服務(wù)器方式

    Redis客戶端連接遠(yuǎn)程Redis服務(wù)器方式

    這篇文章主要介紹了Redis客戶端連接遠(yuǎn)程Redis服務(wù)器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Redis實(shí)現(xiàn)分布式鎖的實(shí)例講解

    Redis實(shí)現(xiàn)分布式鎖的實(shí)例講解

    在本篇文章里小編給大家整理了一篇關(guān)于Redis實(shí)現(xiàn)分布式鎖的實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-12-12
  • Redis實(shí)現(xiàn)高效內(nèi)存管理的示例代碼

    Redis實(shí)現(xiàn)高效內(nèi)存管理的示例代碼

    Redis內(nèi)存管理是其核心功能之一,為了高效地利用內(nèi)存,Redis采用了多種技術(shù)和策略,如優(yōu)化的數(shù)據(jù)結(jié)構(gòu)、內(nèi)存分配策略、內(nèi)存回收、數(shù)據(jù)壓縮等,下面就來(lái)詳細(xì)的介紹一下
    2025-08-08
  • Windows下搭建Redis集群的方法步驟

    Windows下搭建Redis集群的方法步驟

    本文主要介紹了Windows下搭建Redis集群的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Redis之Redisson的可重入鎖原理及解讀

    Redis之Redisson的可重入鎖原理及解讀

    這篇文章主要了Redisson可重入鎖的概念和實(shí)現(xiàn)法,它通過(guò)網(wǎng)吧場(chǎng)景解釋了什么是有鎖和可重入,文中強(qiáng)調(diào)了要使同一把鎖,以及必須成對(duì)unlock(),最后,它還強(qiáng)調(diào)了Redisson的計(jì)數(shù)器和鎖的管理機(jī)制,作者還提供了實(shí)現(xiàn)步驟和注意事項(xiàng)
    2026-04-04

最新評(píng)論

水富县| 抚松县| 图片| 巨鹿县| 新疆| 淮北市| 宁明县| 太康县| 宁远县| 卢湾区| 东乡族自治县| 东阿县| 新营市| 房产| 绿春县| 临邑县| 葵青区| 望谟县| 盐城市| 犍为县| 阳泉市| 新密市| 甘谷县| 泌阳县| 尖扎县| 鹤岗市| 固始县| 建水县| 峨山| 团风县| 馆陶县| 亳州市| 渭源县| 赣州市| 嘉鱼县| 剑阁县| 庆城县| 肃南| 秦皇岛市| 上饶市| 九龙县|