最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Redisson 分布式鎖的正確使用

2022-10-07 00:59 作者:Erwin_Feng  | 我要投稿

背景介紹

前段時間,在寫公司的一個項目的時候,用到了分布式鎖,一個同事告訴我說,分布式鎖解鎖在高并發(fā)的時候會報錯。

下面看下模擬代碼:

simulate-lock

這里鎖的時間是 5 秒,而業(yè)務執(zhí)行的時間是 20 秒。這里模擬的是鎖的時間少于業(yè)務執(zhí)行的時間。

第二次執(zhí)行的時候,就會報錯,如下:

java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 660a38bb-c50b-4117-8ee2-67da7b4303c6 thread-id: 62

錯誤分析

通過這個錯誤信息,也知道該如何解決這個問題,我們只需要判斷是當前線程再去解鎖,就不會報錯的。

可是為什么會報錯呢?

所以,我們需要先去搞清楚具體的執(zhí)行流程。

simulate-lock-marker

最開始,我以為,如果被鎖住,運行到 ① 就會被返回,后面經(jīng)過測試,實際上是會走到第 ② 步,嘗試獲取不到鎖,就會返回,在返回之前呢,會執(zhí)行 finally 的代碼,因為 redisson 對鎖有續(xù)租的功能,所以,這時候鎖還是鎖住的,解鎖就會報錯,也就是第 ③ 步。

實際上,我們的想法的,如果業(yè)務執(zhí)行出錯,我們在 finally 進行解鎖,以防止程序死鎖。

顯然這樣寫代碼,不是我們所期望的,并且代碼也有問題。

優(yōu)化代碼

@RequestMapping("/try-lock")
public?String?tryLock()?{
????
????RLock?rLock?=?redissonClient.getLock("demo-spring-boot-redisson:try-lock");
????if?(Objects.isNull(rLock))?{
????????return?"lock?exception";
????}
????
????boolean?tryLock;
????try?{
????????tryLock?=?rLock.tryLock(3,?60,?TimeUnit.SECONDS);
????}?catch?(InterruptedException?e)?{
????????return?"get?lock?exception";
????}
????if?(!tryLock)?{
????????return?"get?lock?failed";
????}
????
????try?{
????????TimeUnit.SECONDS.sleep(20);
????????return?"success";
????}?catch?(Exception?e)?{
????????return?"business?exception";
????}?finally?{
????????if?(rLock.isLocked()?&&?rLock.isHeldByCurrentThread())?{
????????????rLock.unlock();
????????}
????}
}

以上,便是優(yōu)化后的代碼,我們來一起分析一下。

分布式加鎖主要分為三步。

第一步,主要是獲取 RLock 對象,并且我們對它做了判空。

RLock?rLock?=?redissonClient.getLock("demo-spring-boot-redisson:try-lock");
if?(Objects.isNull(rLock))?{
????return?"lock?exception";
}

第二步,嘗試加鎖,加鎖失敗,返回加鎖失敗。

boolean?tryLock;
try?{
????tryLock?=?rLock.tryLock(3,?60,?TimeUnit.SECONDS);
}?catch?(InterruptedException?e)?{
????return?"get?lock?exception";
}
if?(!tryLock)?{
????return?"get?lock?failed";
}

這里我們用的是 tryLock,第一個參數(shù) waitTime,意思是等待 5 秒,如果還沒獲取到,就不再等待。第二個參數(shù)是 leaseTime,意思是鎖的釋放時間。

第三步,就是我們業(yè)務代碼。

try?{
????TimeUnit.SECONDS.sleep(20);
????return?"success";
}?catch?(Exception?e)?{
????return?"business?exception";
}?finally?{
????if?(rLock.isLocked()?&&?rLock.isHeldByCurrentThread())?{
????????rLock.unlock();
????}
}

在 finally 里,我們做鎖的釋放操作,在釋放之前,我們對鎖的狀態(tài)和是否是當前線程做了判斷。

OK,如果你在實際的業(yè)務中如果遇到什么問題,歡迎留言探討。

引申分析


    1. lock 和 tryLock 區(qū)別?

簡單來說,lock 會一直阻塞,而 tryLock 加鎖失敗,會返回 false。


    1. 如果鎖的時間少于業(yè)務的時間,會怎么樣?

通過上面的分析,我們知道 tryLock 會加鎖失敗,而 lock,在鎖到釋放時間后,即便業(yè)務沒有執(zhí)行完,也會繼續(xù)執(zhí)行,并且不會報錯。

@RequestMapping("/lock")
public?String?lock()?{
????RLock?rLock?=?redissonClient.getLock("demo-spring-boot-redisson:lock");
????if?(Objects.isNull(rLock))?{
????????return?"exception";
????}
????try?{
????????rLock.lock(5,?TimeUnit.SECONDS);
????????System.out.println("execute?business");
????????TimeUnit.SECONDS.sleep(20);
????????return?"success";
????}?catch?(Exception?e)?{
????????return?"lock?exception";
????}?finally?{
????????if?(rLock.isLocked())?{
????????????rLock.unlock();
????????}
????}
}


    1. 在解鎖的時候,不判斷鎖的狀態(tài),會報錯嗎,反正都會解鎖?

tryLock 不會。

而 lock 會報錯,報錯信息如下:

java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 8b7b0374-506b-442f-9bc4-9e1c1cbf4d46 thread-id: 61


Redisson 分布式鎖的正確使用的評論 (共 條)

分享到微博請遵守國家法律
大安市| 门源| 开远市| 新野县| 康保县| 尤溪县| 乐都县| 遵化市| 观塘区| 吉木萨尔县| 宣武区| 莆田市| 左贡县| 庐江县| 方山县| 唐海县| 保山市| 枣庄市| 柳江县| 静宁县| 文登市| 九台市| 顺昌县| 孟村| 房山区| 云安县| 舞钢市| 大石桥市| 武定县| 赣州市| 巍山| 罗江县| 洮南市| 永春县| 沂南县| 临澧县| 芷江| 尉氏县| 洛南县| 逊克县| 广州市|