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

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

 更新時(shí)間:2026年04月25日 16:52:15   作者:風(fēng)吹迎面入袖涼  
這篇文章主要了Redisson可重入鎖的概念和實(shí)現(xiàn)法,它通過網(wǎng)吧場景解釋了什么是有鎖和可重入,文中強(qiáng)調(diào)了要使同一把鎖,以及必須成對(duì)unlock(),最后,它還強(qiáng)調(diào)了Redisson的計(jì)數(shù)器和鎖的管理機(jī)制,作者還提供了實(shí)現(xiàn)步驟和注意事項(xiàng)

一. 什么是可重入鎖?

假設(shè)你去網(wǎng)吧上網(wǎng),網(wǎng)吧里的每臺(tái)電腦(比如1號(hào)機(jī))就是“一把鎖”,開機(jī)密碼(或身份證刷卡)就是“拿鎖的權(quán)限”,你就是程序里的“線程”——只有你刷了卡、開了機(jī),才能用這臺(tái)電腦,別人不能用,這就是“鎖”的作用(保證同一時(shí)間,只有一個(gè)線程能操作資源)。

場景1(可重入,正常情況):你刷身份證開機(jī),用1號(hào)機(jī)(相當(dāng)于“線程拿到鎖”),玩了一會(huì)兒,想去廁所(相當(dāng)于程序里“一個(gè)方法調(diào)用另一個(gè)方法,兩個(gè)方法都需要同一把鎖”),你不用關(guān)機(jī)、釋放1號(hào)機(jī)(不用釋放鎖),直接起身去廁所,回來后還能直接坐回1號(hào)機(jī)、繼續(xù)玩——這就是“可重入”,怎么拿、怎么用,不卡殼,不用等自己“釋放”電腦,也不會(huì)卡死。

場景2(不可重入,卡死情況):如果這臺(tái)電腦是“不可重入”的,你開機(jī)用了1號(hào)機(jī)后,想去廁所,必須先關(guān)機(jī)、釋放1號(hào)機(jī)(釋放鎖),才能起身;等你從廁所回來,想再用1號(hào)機(jī),還得重新刷卡開機(jī)(重新拿鎖)。可你根本不想關(guān)機(jī)(業(yè)務(wù)還沒做完),一旦關(guān)機(jī),之前玩的內(nèi)容就沒了,不關(guān)機(jī)又沒法起身——這就是程序里的“死鎖”,程序直接卡死,沒法繼續(xù)運(yùn)行。

對(duì)應(yīng)到程序里,再簡單說一句:你寫了兩個(gè)方法A和B,兩個(gè)方法都需要同一把鎖(相當(dāng)于都需要用1號(hào)機(jī)),方法A里會(huì)調(diào)用方法B(相當(dāng)于用1號(hào)機(jī)時(shí),中途要做另一個(gè)需要用1號(hào)機(jī)的操作)。用Redisson可重入鎖,程序執(zhí)行A、再調(diào)用B時(shí),能直接執(zhí)行,不卡頓;用不可重入鎖,程序會(huì)卡在B那里,自己等自己釋放鎖,永遠(yuǎn)等不到,直接卡死。

二、怎么實(shí)現(xiàn)的“重入”?

可重入鎖主要用計(jì)數(shù)器實(shí)現(xiàn)的。計(jì)數(shù)器的唯一作用,就是記著你“拿了幾次鎖”,避免“釋放一次就把鎖徹底放走”,也避免自己卡死自己,全程由Redisson自動(dòng)管理,我們不用手動(dòng)操作。

具體工作流程:

  • 你第一次刷身份證,開機(jī)用1號(hào)機(jī)(線程第一次獲取鎖),Redisson的計(jì)數(shù)器就記1(相當(dāng)于“你第一次占用1號(hào)機(jī)”);
  • 你玩到中途,想重啟電腦(相當(dāng)于程序里“方法A調(diào)用方法B,再次獲取同一把鎖”),因?yàn)槭悄惚救耍ㄍ粋€(gè)線程),Redisson不用讓你重新刷卡,直接把計(jì)數(shù)器加1,變成2(相當(dāng)于“你第二次占用1號(hào)機(jī)”);
  • 重啟完成,你繼續(xù)玩(相當(dāng)于methodB執(zhí)行完),釋放一次鎖,計(jì)數(shù)器就減1,變成1(相當(dāng)于“你釋放了一次占用,但還在使用1號(hào)機(jī)”);
  • 你玩完了,關(guān)機(jī)離開(相當(dāng)于methodA執(zhí)行完),再釋放一次鎖,計(jì)數(shù)器減1,變成0(相當(dāng)于“你徹底釋放1號(hào)機(jī)”);
  • 只有計(jì)數(shù)器變成0,這把鎖才真正放開,其他人才可以刷身份證、開機(jī)用1號(hào)機(jī)(其他線程才能獲取這把鎖)。

重點(diǎn)提醒:如果沒有計(jì)數(shù)器,會(huì)出什么問題?

就像你在網(wǎng)吧,重啟電腦(釋放一次鎖)后,計(jì)數(shù)器沒記錄,系統(tǒng)會(huì)誤以為你“徹底離開”,直接把1號(hào)機(jī)釋放,別人可能趁你還在座位上,就刷卡開機(jī)——對(duì)應(yīng)程序里,就是“鎖提前釋放”,多個(gè)線程同時(shí)操作一個(gè)資源(比如同時(shí)改一個(gè)數(shù)據(jù)),會(huì)導(dǎo)致數(shù)據(jù)錯(cuò)亂、程序出問題。

補(bǔ)充一句:

Redisson已經(jīng)幫我們把“計(jì)數(shù)器”“線程標(biāo)識(shí)”(識(shí)別是不是同一個(gè)線程拿鎖)全部封裝好了,我們不用自己寫一行代碼管理計(jì)數(shù)器,只需要調(diào)用簡單的lock()(拿鎖)和unlock()(釋放鎖),就能實(shí)現(xiàn)可重入,這也是Redisson比其他Redis客戶端好用的地方。

三、Redisson可重入鎖怎么用?

第一步:準(zhǔn)備環(huán)境

1. 給項(xiàng)目加依賴:

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.3</version>
</dependency>

2. 配置Redis(復(fù)制到application.yml里,只改2個(gè)地方:Redis地址、Redis密碼,沒有密碼就刪掉密碼那一行):

spring:
  redis:
    host: 127.0.0.1  # 改成你自己的Redis地址,本地開發(fā)就是127.0.0.1
    port: 6379       # 默認(rèn)端口,一般不用改
    password: 123456 # 改成你自己的Redis密碼,沒有就刪掉這一行
redisson:
  singleServerConfig:
    address: redis://127.0.0.1:6379  # 和上面的Redis地址、端口一致
    password: 123456 # 和上面的Redis密碼一致,沒有就刪掉這一行

第二步:寫核心代碼

我們寫一個(gè)服務(wù)類,里面有兩個(gè)方法(methodA和methodB),methodA調(diào)用methodB,兩個(gè)方法都用同一把鎖,模擬“重入”場景(對(duì)應(yīng)網(wǎng)吧里“開機(jī)后重啟電腦”的場景),代碼里的注釋都寫得很直白,一看就懂,直接復(fù)制粘貼到項(xiàng)目里就行:

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
// 這個(gè)注解不用管,加了就能用
@Service
public class LockDemo {
    // 注入Redisson,不用管怎么來的,加了依賴就能自動(dòng)注入
    @Autowired
    private RedissonClient redissonClient;
    // 鎖的名字,必須唯一,相當(dāng)于網(wǎng)吧1號(hào)機(jī)的“編號(hào)”,兩個(gè)方法必須用同一個(gè)名字
    private static final String LOCK_NAME = "myLock";
    // 方法A:需要拿鎖(相當(dāng)于網(wǎng)吧開機(jī)用1號(hào)機(jī))
    public void methodA() {
        // 1. 獲取可重入鎖(拿鎖,就是刷身份證拿1號(hào)機(jī)的使用權(quán))
        RLock lock = redissonClient.getLock(LOCK_NAME);
        try {
            // 2. 加鎖(開機(jī)),不用管其他的,調(diào)用這個(gè)方法就好
            lock.lock();
            System.out.println("程序(線程)進(jìn)入methodA,拿到鎖了(相當(dāng)于開機(jī)用1號(hào)機(jī))");
            // 3. 調(diào)用methodB,methodB也需要同一把鎖(相當(dāng)于開機(jī)后重啟電腦,再次占用1號(hào)機(jī))
            methodB();
            // 模擬業(yè)務(wù)操作(比如存數(shù)據(jù)、改數(shù)據(jù)),不用改,照搬就行
            Thread.sleep(1000);
        } catch (Exception e) {
            // 出錯(cuò)了也不用管,這里只是防止程序崩潰
            e.printStackTrace();
        } finally {
            // 4. 釋放鎖(關(guān)機(jī)),必須寫在這里,防止程序出錯(cuò)后鎖沒釋放
            lock.unlock();
            System.out.println("程序(線程)退出methodA,釋放鎖了(相當(dāng)于關(guān)機(jī)離開1號(hào)機(jī))");
        }
    }
    // 方法B:也需要拿同一把鎖(相當(dāng)于重啟電腦,再次占用1號(hào)機(jī))
    public void methodB() {
        // 還是同一把鎖(LOCK_NAME和上面一樣,相當(dāng)于還是1號(hào)機(jī))
        RLock lock = redissonClient.getLock(LOCK_NAME);
        try {
            // 加鎖(重啟電腦),因?yàn)槭峭粋€(gè)程序,直接重入,不用等
            lock.lock();
            System.out.println("程序(線程)進(jìn)入methodB,重入鎖成功(相當(dāng)于重啟電腦,繼續(xù)用1號(hào)機(jī))");
            // 模擬業(yè)務(wù)操作,不用改
            Thread.sleep(500);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 釋放鎖(重啟完成),計(jì)數(shù)器減1,不是徹底釋放
            lock.unlock();
            System.out.println("程序(線程)退出methodB,釋放重入鎖(相當(dāng)于重啟完成,繼續(xù)使用1號(hào)機(jī))");
        }
    }
}

第三步:測試

寫一個(gè)簡單的測試接口,調(diào)用上面的methodA,看控制臺(tái)輸出,就能知道可重入鎖有沒有生效,代碼還是復(fù)制粘貼:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
// 測試接口,不用改
@RestController
public class TestLockController {
    // 注入上面寫的LockDemo類
    @Autowired
    private LockDemo lockDemo;
    // 訪問這個(gè)接口,就能測試可重入鎖
    @GetMapping("/testLock")
    public String testLock() {
        // 調(diào)用methodA,會(huì)自動(dòng)調(diào)用methodB,模擬重入場景
        lockDemo.methodA();
        return "測試成功!去看控制臺(tái)輸出";
    }
}

測試結(jié)果

啟動(dòng)項(xiàng)目,訪問接口(http://localhost:8080/testLock),打開控制臺(tái),會(huì)看到下面的輸出(順序不能亂):

程序(線程)進(jìn)入methodA,拿到鎖了(相當(dāng)于開機(jī)用1號(hào)機(jī))
程序(線程)進(jìn)入methodB,重入鎖成功(相當(dāng)于重啟電腦,繼續(xù)用1號(hào)機(jī))
程序(線程)退出methodB,釋放重入鎖(相當(dāng)于重啟完成,繼續(xù)使用1號(hào)機(jī))
程序(線程)退出methodA,釋放鎖了(相當(dāng)于關(guān)機(jī)離開1號(hào)機(jī))?

解讀一下這個(gè)結(jié)果:

程序先進(jìn)入methodA、拿到鎖(開機(jī)用1號(hào)機(jī)),然后直接進(jìn)入methodB(重入成功,相當(dāng)于重啟電腦,不用重新刷卡),再依次釋放methodB、methodA的鎖(重啟完成→關(guān)機(jī)離開)——這就證明可重入鎖生效了,Redisson的計(jì)數(shù)器也在正常工作(拿2次、放2次,最后徹底釋放)。

四、注意事項(xiàng)

  • 同一把鎖的名字必須一致:相當(dāng)于網(wǎng)吧里“1號(hào)機(jī)器”的鎖,你開機(jī)用了1號(hào)機(jī)(拿鎖),中途去廁所回來,還想坐1號(hào)機(jī)(重入鎖),必須找的是“1號(hào)機(jī)”的鎖,不能找“2號(hào)機(jī)”的鎖——對(duì)應(yīng)代碼里,methodA和methodB用的LOCK_NAME,必須都是“myLock”,不能一個(gè)寫“myLock”、一個(gè)寫“myLock1”,否則不是同一把鎖,沒法重入。
  • lock()和unlock()要成對(duì)出現(xiàn):相當(dāng)于你去網(wǎng)吧,開機(jī)(lock()拿鎖)、關(guān)機(jī)(unlock()釋放鎖)要對(duì)應(yīng)。你開了一次機(jī),就必須關(guān)一次機(jī);開兩次機(jī)(比如開機(jī)后又重啟一次,相當(dāng)于重入),就必須關(guān)兩次機(jī)。多關(guān)一次(多unlock()),系統(tǒng)會(huì)報(bào)錯(cuò);少關(guān)一次(少unlock()),這臺(tái)機(jī)器會(huì)一直顯示“已占用”,別人沒法用(鎖泄漏)。
  • unlock()必須寫在finally里:相當(dāng)于你在網(wǎng)吧上網(wǎng),不管是正常關(guān)機(jī)(業(yè)務(wù)正常執(zhí)行),還是突然停電、電腦死機(jī)(程序出錯(cuò)),機(jī)器都會(huì)自動(dòng)釋放(關(guān)機(jī)),不會(huì)一直占著位置。如果不寫在finally里,程序一出錯(cuò),就沒人“關(guān)機(jī)”,這臺(tái)機(jī)器永遠(yuǎn)被占用,別人用不了。

五、總結(jié)

可重入鎖:你在網(wǎng)吧坐1號(hào)機(jī)(拿鎖),中途去廁所、重啟電腦(重入),回來還能直接坐1號(hào)機(jī),不用等自己“釋放”機(jī)器,不卡頓;

Redisson核心原理:靠“計(jì)數(shù)器”記拿鎖次數(shù),拿一次加1,放一次減1,減到0才徹底釋放鎖,避免提前釋放和死鎖;

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

相關(guān)文章

  • Redis Cluster設(shè)置密碼修改密碼過程

    Redis Cluster設(shè)置密碼修改密碼過程

    這篇文章主要介紹了Redis Cluster設(shè)置密碼修改密碼過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2026-06-06
  • Redis6 主從復(fù)制及哨兵機(jī)制的實(shí)現(xiàn)

    Redis6 主從復(fù)制及哨兵機(jī)制的實(shí)現(xiàn)

    本文主要介紹了Redis6 主從復(fù)制及哨兵機(jī)制的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Window server中安裝Redis的超詳細(xì)教程

    Window server中安裝Redis的超詳細(xì)教程

    這篇文章主要介紹了Window server中安裝Redis的教程,本文通過圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-11-11
  • redis保存AtomicInteger對(duì)象踩坑及解決

    redis保存AtomicInteger對(duì)象踩坑及解決

    這篇文章主要介紹了redis保存AtomicInteger對(duì)象踩坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 在CenOS系統(tǒng)下安裝和配置Redis數(shù)據(jù)庫的教程

    在CenOS系統(tǒng)下安裝和配置Redis數(shù)據(jù)庫的教程

    這篇文章主要介紹了在CenOS系統(tǒng)下安裝和配置Redis數(shù)據(jù)庫的教程,Redis是一個(gè)可基于內(nèi)存的高性能NoSQL數(shù)據(jù)庫,需要的朋友可以參考下
    2015-11-11
  • Redis分布式鎖的超時(shí)機(jī)制實(shí)現(xiàn)的方法示例

    Redis分布式鎖的超時(shí)機(jī)制實(shí)現(xiàn)的方法示例

    本文介紹了Redis分布式鎖中超時(shí)機(jī)制的關(guān)鍵作用,通過設(shè)置鎖的過期時(shí)間防止客戶端崩潰導(dǎo)致的死鎖問題,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-10-10
  • Redis如何使用HyperLogLog的實(shí)現(xiàn)

    Redis如何使用HyperLogLog的實(shí)現(xiàn)

    本文主要介紹了Redis如何使用HyperLogLog的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • SpringBoot 集成Redis 過程

    SpringBoot 集成Redis 過程

    redis是一個(gè)開源的、使用C語言編寫的、支持網(wǎng)絡(luò)交互的、可基于內(nèi)存也可持久化的Key-Value數(shù)據(jù)庫。本文給大家介紹SpringBoot 集成Redis 過程,感興趣的朋友一起看看吧
    2021-06-06
  • Redis優(yōu)惠券秒殺解決方案

    Redis優(yōu)惠券秒殺解決方案

    這篇文章主要介紹了Redis解決優(yōu)惠券秒殺應(yīng)用案例,本文先講了搶購問題,指出其中會(huì)出現(xiàn)的多線程問題,提出解決方案采用悲觀鎖和樂觀鎖兩種方式進(jìn)行實(shí)現(xiàn),然后發(fā)現(xiàn)在搶購過程中容易出現(xiàn)一人多單現(xiàn)象,需要的朋友可以參考下
    2022-12-12
  • Redis在windows環(huán)境下如何啟動(dòng)

    Redis在windows環(huán)境下如何啟動(dòng)

    這篇文章主要介紹了Redis在windows環(huán)境下如何啟動(dòng)的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04

最新評(píng)論

任丘市| 寿宁县| 青州市| 永定县| 平原县| 安国市| 洪江市| 方山县| 茂名市| 新营市| 上高县| 开江县| 依兰县| 永州市| 两当县| 察雅县| 林西县| 灵台县| 交口县| 青海省| 岚皋县| 普洱| 郎溪县| 綦江县| 潞西市| 宾川县| 汶上县| 龙门县| 惠东县| 杭州市| 西丰县| 阜城县| 遂川县| 二连浩特市| 汶川县| 炎陵县| 杨浦区| 通化市| 遵化市| 石河子市| 广平县|