亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

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

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

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

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

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

tryLock()

@Override
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
    // 轉成毫秒,后面都是以毫秒為單位
    long time = unit.toMillis(waitTime);
    // 當前時間
    long current = System.currentTimeMillis();
    // 線程ID-線程標識
    long threadId = Thread.currentThread().getId();
 
    // 嘗試獲取鎖 tryAcquire() !!!
    Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
        
    // 如果上面嘗試獲取鎖返回的是null,表示成功;如果返回的是時間則表示失敗。
    if (ttl == null) {
        return true;
    }
 
    // 剩余等待時間 = 最大等待時間 -(用現(xiàn)在時間 - 獲取鎖前的時間)
    time -= System.currentTimeMillis() - current;
 
    // 剩余等待時間 < 0 失敗
    if (time <= 0) {
        acquireFailed(waitTime, unit, threadId);
        return false;
    }
 
    // 再次獲取當前時間
    current = System.currentTimeMillis();
    // 重試邏輯,但不是簡單的直接重試!
    // subscribe是訂閱的意思
    RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
    // 如果在剩余等待時間內,收到了釋放鎖那邊發(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 {
        // 又重新計算了一下,上述的等待時間
        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;
            }
            
            // 又獲取鎖失敗,再次計算上面的耗時
            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);
            }
            
            // 重新計算時間(充足就繼續(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 {
 
	// 獲取當前線程 ID
    long threadId = Thread.currentThread().getId();
    // 獲取鎖,正常獲取鎖則ttl為null,競爭鎖時返回鎖的過期時間
    Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
    if (ttl == null) {
        return;
    }
		
    // 訂閱鎖釋放事件
    // 如果當前線程通過 Redis 的 channel 訂閱鎖的釋放事件獲取得知已經(jīng)被釋放,則會發(fā)消息通知待等待的線程進行競爭
    RFuture<RedissonLockEntry> future = subscribe(threadId);
    if (interruptibly) {
        commandExecutor.syncSubscriptionInterrupted(future);
    } else {
        commandExecutor.syncSubscription(future);
    }
 
    try {
        while (true) {
            // 循環(huán)重試獲取鎖,直至重新獲取鎖成功才跳出循環(huán)
            // 此種做法阻塞進程,一直處于等待鎖手動釋放或者超時才繼續(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);
    }
}

建議應盡量使用tryLock(),且攜帶參數(shù),因為可設置最大等待時間以及可及時獲取加鎖返回值,后續(xù)可做一些其他加鎖失敗的業(yè)務

總結

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

相關文章

  • Redis實現(xiàn)多人多聊天室功能

    Redis實現(xiàn)多人多聊天室功能

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

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

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

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

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

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

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

    淺談Redis中LFU算法源碼解析

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

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

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

    antd為Tree組件標題附加操作按鈕功能

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

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

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

    redis中刪除操作命令

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

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

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

最新評論