欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

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

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

(1)返回值: lock() 是沒有返回值的;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)識
    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();
    // 重試邏輯,但不是簡單的直接重試!
    // subscribe是訂閱的意思
    RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
    // 如果在剩余等待時(shí)間內(nèi),收到了釋放鎖那邊發(fā)過來的publish,則才會再次嘗試獲取鎖
    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();
            // 采用信號量的方式重試!
            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,競爭鎖時(shí)返回鎖的過期時(shí)間
    Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
    if (ttl == null) {
        return;
    }
		
    // 訂閱鎖釋放事件
    // 如果當(dāng)前線程通過 Redis 的 channel 訂閱鎖的釋放事件獲取得知已經(jīng)被釋放,則會發(fā)消息通知待等待的線程進(jìn)行競爭
    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)多人多聊天室功能

    這篇文章主要為大家詳細(xì)介紹了Redis實(shí)現(xiàn)多人多聊天室功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Redis實(shí)現(xiàn)全局唯一id的使用示例

    Redis實(shí)現(xiàn)全局唯一id的使用示例

    全局ID生成器,是一種在分布式系統(tǒng)下用來生成全局唯一ID的工具,本文主要介紹了Redis實(shí)現(xiàn)全局唯一id的使用示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • redis的五大數(shù)據(jù)類型應(yīng)用場景分析

    redis的五大數(shù)據(jù)類型應(yīng)用場景分析

    這篇文章主要介紹了redis的五大數(shù)據(jù)類型實(shí)現(xiàn)原理,本文給大家分享五大數(shù)據(jù)類型的應(yīng)用場景分析,需要的朋友可以參考下
    2021-08-08
  • Redis 2.8-4.0過期鍵優(yōu)化過程全紀(jì)錄

    Redis 2.8-4.0過期鍵優(yōu)化過程全紀(jì)錄

    這篇文章主要給大家介紹了關(guān)于Redis 2.8-4.0過期鍵優(yōu)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 淺談Redis中LFU算法源碼解析

    淺談Redis中LFU算法源碼解析

    Redis的LFU淘汰算法主要用于?maxmemory-policy?設(shè)置為allkeys-lfu或volatile-lfu時(shí),以最少使用頻率的鍵進(jìn)行淘汰,本文主要介紹了淺談Redis中LFU算法源碼解析,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • 一文詳解Redis為什么一定要設(shè)置密碼原理

    一文詳解Redis為什么一定要設(shè)置密碼原理

    這篇文章主要為大家介紹了Redis為什么一定要設(shè)置密碼原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • antd為Tree組件標(biāo)題附加操作按鈕功能

    antd為Tree組件標(biāo)題附加操作按鈕功能

    這篇文章主要介紹了antd為Tree組件標(biāo)題附加操作按鈕功能,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • 解決redis修改requirepass后不生效的問題

    解決redis修改requirepass后不生效的問題

    今天小編就為大家分享一篇解決redis修改requirepass后不生效的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • redis中刪除操作命令

    redis中刪除操作命令

    這篇文章主要介紹了redis中刪除操作命令,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Redis實(shí)現(xiàn)編碼生成規(guī)則方式

    Redis實(shí)現(xiàn)編碼生成規(guī)則方式

    在自動(dòng)生成編碼時(shí)應(yīng)采用“MD+年月日+4位序列號”的規(guī)則,如“MD202310130001”,為避免使用隨機(jī)序列號導(dǎo)致的重復(fù)編碼,建議使用從0開始的自增序列號,此外,使用Redis的incrBy功能實(shí)現(xiàn)序列號自增,可以有效提高效率和降低實(shí)現(xiàn)難度
    2023-01-01

最新評論