實(shí)操Redission 分布式鎖和同步器

1. 可重入鎖(Reentrant Lock)

概念:所謂重入鎖惨远,指的是以線程為單位奶段,當(dāng)一個(gè)線程獲取對(duì)象鎖之后微峰,這個(gè)線程可以再次獲取本對(duì)象上的鎖沙兰,而其他的線程是不可以的

基于Redis的Redisson分布式可重入鎖RLock Java對(duì)象實(shí)現(xiàn)了java.util.concurrent.locks.Lock接口氓奈。同時(shí)還提供了異步(Async)反射式(Reactive)RxJava2標(biāo)準(zhǔn)的接口鼎天。

RLock lock = redisson.getLock("anyLock");
// 最常見的使用方法
lock.lock();

大家都知道舀奶,如果負(fù)責(zé)儲(chǔ)存這個(gè)分布式鎖的Redisson節(jié)點(diǎn)宕機(jī)以后,而且這個(gè)鎖正好處于鎖住的狀態(tài)時(shí)斋射,這個(gè)鎖會(huì)出現(xiàn)鎖死的狀態(tài)育勺。為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗罗岖,它的作用是在Redisson實(shí)例被關(guān)閉前涧至,不斷的延長鎖的有效期。默認(rèn)情況下桑包,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘南蓬,也可以通過修改Config.lockWatchdogTimeout來另行指定。

另外Redisson還通過加鎖的方法提供了leaseTime的參數(shù)來指定加鎖的時(shí)間哑了。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了赘方。

// 加鎖以后10秒鐘自動(dòng)解鎖
// 無需調(diào)用unlock方法手動(dòng)解鎖
lock.lock(10, TimeUnit.SECONDS);

// 嘗試加鎖,最多等待100秒弱左,上鎖以后10秒自動(dòng)解鎖
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     ...
   } finally {
       lock.unlock();
   }
}

Redisson同時(shí)還為分布式鎖提供了異步執(zhí)行的相關(guān)方法:

RLock lock = redisson.getLock("anyLock");
lock.lockAsync();
lock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = lock.tryLockAsync(100, 10, TimeUnit.SECONDS);

RLock對(duì)象完全符合Java的Lock規(guī)范窄陡。也就是說只有擁有鎖的進(jìn)程才能解鎖,其他進(jìn)程解鎖則會(huì)拋出IllegalMonitorStateException錯(cuò)誤拆火。但是如果遇到需要其他進(jìn)程也能解鎖的情況跳夭,請(qǐng)使用分布式信號(hào)量Semaphore 對(duì)象.

2. 公平鎖(Fair Lock)

概念:每個(gè)線程搶占鎖的順序?yàn)橄群笳{(diào)用lock方法的順序依次獲取鎖涂圆,類似于排隊(duì)吃飯

基于Redis的Redisson分布式可重入公平鎖也是實(shí)現(xiàn)了java.util.concurrent.locks.Lock接口的一種RLock對(duì)象。同時(shí)還提供了異步(Async)优妙、反射式(Reactive)RxJava2標(biāo)準(zhǔn)的接口乘综。它保證了當(dāng)多個(gè)Redisson客戶端線程同時(shí)請(qǐng)求加鎖時(shí),優(yōu)先分配給先發(fā)出請(qǐng)求的線程套硼。所有請(qǐng)求線程會(huì)在一個(gè)隊(duì)列中排隊(duì)卡辰,當(dāng)某個(gè)線程出現(xiàn)宕機(jī)時(shí),Redisson會(huì)等待5秒后繼續(xù)下一個(gè)線程邪意,也就是說如果前面有5個(gè)線程都處于等待狀態(tài)九妈,那么后面的線程會(huì)等待至少25秒。

RLock fairLock = redisson.getFairLock("anyLock");
// 最常見的使用方法
fairLock.lock();

大家都知道雾鬼,如果負(fù)責(zé)儲(chǔ)存這個(gè)分布式鎖的Redis節(jié)點(diǎn)宕機(jī)以后萌朱,而且這個(gè)鎖正好處于鎖住的狀態(tài)時(shí),這個(gè)鎖會(huì)出現(xiàn)鎖死的狀態(tài)策菜。為了避免這種情況的發(fā)生晶疼,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗,它的作用是在Redisson實(shí)例被關(guān)閉前又憨,不斷的延長鎖的有效期翠霍。默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘蠢莺,也可以通過修改Config.lockWatchdogTimeout來另行指定寒匙。

另外Redisson還通過加鎖的方法提供了leaseTime的參數(shù)來指定加鎖的時(shí)間。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了躏将。

// 10秒鐘以后自動(dòng)解鎖
// 無需調(diào)用unlock方法手動(dòng)解鎖
fairLock.lock(10, TimeUnit.SECONDS);

// 嘗試加鎖锄弱,最多等待100秒,上鎖以后10秒自動(dòng)解鎖
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
...
fairLock.unlock();

Redisson同時(shí)還為分布式可重入公平鎖提供了異步執(zhí)行的相關(guān)方法:

RLock fairLock = redisson.getFairLock("anyLock");
fairLock.lockAsync();
fairLock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = fairLock.tryLockAsync(100, 10, TimeUnit.SECONDS);

3. 聯(lián)鎖(MultiLock)

基于Redis的Redisson分布式聯(lián)鎖RedissonMultiLock對(duì)象可以將多個(gè)RLock對(duì)象關(guān)聯(lián)為一個(gè)聯(lián)鎖祸憋,每個(gè)RLock對(duì)象實(shí)例可以來自于不同的Redisson實(shí)例会宪。

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 同時(shí)加鎖:lock1 lock2 lock3
// 所有的鎖都上鎖成功才算成功。
lock.lock();
...
lock.unlock();

大家都知道夺衍,如果負(fù)責(zé)儲(chǔ)存某些分布式鎖的某些Redis節(jié)點(diǎn)宕機(jī)以后狈谊,而且這些鎖正好處于鎖住的狀態(tài)時(shí),這些鎖會(huì)出現(xiàn)鎖死的狀態(tài)沟沙。為了避免這種情況的發(fā)生河劝,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗,它的作用是在Redisson實(shí)例被關(guān)閉前矛紫,不斷的延長鎖的有效期赎瞎。默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘颊咬,也可以通過修改Config.lockWatchdogTimeout來另行指定务甥。

另外Redisson還通過加鎖的方法提供了leaseTime的參數(shù)來指定加鎖的時(shí)間牡辽。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了。

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 給lock1敞临,lock2态辛,lock3加鎖,如果沒有手動(dòng)解開的話挺尿,10秒鐘后將會(huì)自動(dòng)解開
lock.lock(10, TimeUnit.SECONDS);

// 為加鎖等待100秒時(shí)間奏黑,并在加鎖成功10秒鐘后自動(dòng)解開
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

4.紅鎖(RedLock)

基于Redis的Redisson紅鎖RedissonRedLock對(duì)象實(shí)現(xiàn)了Redlock介紹的加鎖算法。該對(duì)象也可以用來將多個(gè)RLock對(duì)象關(guān)聯(lián)為一個(gè)紅鎖编矾,每個(gè)RLock對(duì)象實(shí)例可以來自于不同的Redisson實(shí)例熟史。

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同時(shí)加鎖:lock1 lock2 lock3
// 紅鎖在大部分節(jié)點(diǎn)上加鎖成功就算成功。
lock.lock();
...
lock.unlock();

大家都知道窄俏,如果負(fù)責(zé)儲(chǔ)存某些分布式鎖的某些Redis節(jié)點(diǎn)宕機(jī)以后蹂匹,而且這些鎖正好處于鎖住的狀態(tài)時(shí),這些鎖會(huì)出現(xiàn)鎖死的狀態(tài)凹蜈。為了避免這種情況的發(fā)生限寞,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗,它的作用是在Redisson實(shí)例被關(guān)閉前仰坦,不斷的延長鎖的有效期昆烁。默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘缎岗,也可以通過修改Config.lockWatchdogTimeout來另行指定。

另外Redisson還通過加鎖的方法提供了leaseTime的參數(shù)來指定加鎖的時(shí)間白粉。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了传泊。

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 給lock1,lock2鸭巴,lock3加鎖眷细,如果沒有手動(dòng)解開的話,10秒鐘后將會(huì)自動(dòng)解開
lock.lock(10, TimeUnit.SECONDS);

// 為加鎖等待100秒時(shí)間鹃祖,并在加鎖成功10秒鐘后自動(dòng)解開
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

5. 讀寫鎖(ReadWriteLock)

基于Redis的Redisson分布式可重入讀寫鎖RReadWriteLock Java對(duì)象實(shí)現(xiàn)了java.util.concurrent.locks.ReadWriteLock接口溪椎。其中讀鎖和寫鎖都繼承了RLock接口。

分布式可重入讀寫鎖允許同時(shí)有多個(gè)讀鎖和一個(gè)寫鎖處于加鎖狀態(tài)恬口。

RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常見的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();

大家都知道校读,如果負(fù)責(zé)儲(chǔ)存這個(gè)分布式鎖的Redis節(jié)點(diǎn)宕機(jī)以后,而且這個(gè)鎖正好處于鎖住的狀態(tài)時(shí)祖能,這個(gè)鎖會(huì)出現(xiàn)鎖死的狀態(tài)歉秫。為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗养铸,它的作用是在Redisson實(shí)例被關(guān)閉前雁芙,不斷的延長鎖的有效期轧膘。默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘兔甘,也可以通過修改Config.lockWatchdogTimeout來另行指定谎碍。

另外Redisson還通過加鎖的方法提供了leaseTime的參數(shù)來指定加鎖的時(shí)間。超過這個(gè)時(shí)間后鎖便自動(dòng)解開了洞焙。

// 10秒鐘以后自動(dòng)解鎖
// 無需調(diào)用unlock方法手動(dòng)解鎖
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// 或
rwlock.writeLock().lock(10, TimeUnit.SECONDS);

// 嘗試加鎖蟆淀,最多等待100秒,上鎖以后10秒自動(dòng)解鎖
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// 或
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

6.信號(hào)量(Semaphore)

基于Redis的Redisson的分布式信號(hào)量(Semaphore)Java對(duì)象RSemaphore采用了與java.util.concurrent.Semaphore相似的接口和用法闽晦。同時(shí)還提供了異步(Async)扳碍、反射式(Reactive)RxJava2標(biāo)準(zhǔn)的接口。

RSemaphore semaphore = redisson.getSemaphore("semaphore");
semaphore.acquire();
//或
semaphore.acquireAsync();
semaphore.acquire(23);
semaphore.tryAcquire();
//或
semaphore.tryAcquireAsync();
semaphore.tryAcquire(23, TimeUnit.SECONDS);
//或
semaphore.tryAcquireAsync(23, TimeUnit.SECONDS);
semaphore.release(10);
semaphore.release();
//或
semaphore.releaseAsync();

7. 可過期性信號(hào)量(PermitExpirableSemaphore)

基于Redis的Redisson可過期性信號(hào)量(PermitExpirableSemaphore)是在RSemaphore對(duì)象的基礎(chǔ)上仙蛉,為每個(gè)信號(hào)增加了一個(gè)過期時(shí)間笋敞。每個(gè)信號(hào)可以通過獨(dú)立的ID來辨識(shí),釋放時(shí)只能通過提交這個(gè)ID才能釋放荠瘪。它提供了異步(Async)夯巷、反射式(Reactive)RxJava2標(biāo)準(zhǔn)的接口。

RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");
String permitId = semaphore.acquire();
// 獲取一個(gè)信號(hào)哀墓,有效期只有2秒鐘趁餐。
String permitId = semaphore.acquire(2, TimeUnit.SECONDS);
// ...
semaphore.release(permitId);

8. 閉鎖(CountDownLatch)

基于Redisson的Redisson分布式閉鎖(CountDownLatch)Java對(duì)象RCountDownLatch采用了與java.util.concurrent.CountDownLatch相似的接口和用法。

RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(1);
latch.await();

// 在其他線程或其他JVM里
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.countDown();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末篮绰,一起剝皮案震驚了整個(gè)濱河市后雷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吠各,老刑警劉巖臀突,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贾漏,居然都是意外死亡候学,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門纵散,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梳码,“玉大人,你說我怎么就攤上這事伍掀£瑁” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵蜜笤,是天一觀的道長符匾。 經(jīng)常有香客問我,道長瘩例,這世上最難降的妖魔是什么啊胶? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任甸各,我火速辦了婚禮,結(jié)果婚禮上焰坪,老公的妹妹穿的比我還像新娘趣倾。我一直安慰自己,他們只是感情好某饰,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布儒恋。 她就那樣靜靜地躺著,像睡著了一般黔漂。 火紅的嫁衣襯著肌膚如雪诫尽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天炬守,我揣著相機(jī)與錄音牧嫉,去河邊找鬼。 笑死减途,一個(gè)胖子當(dāng)著我的面吹牛酣藻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鳍置,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼辽剧,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了税产?” 一聲冷哼從身側(cè)響起怕轿,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辟拷,沒想到半個(gè)月后撤卢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梧兼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了智听。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羽杰。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖到推,靈堂內(nèi)的尸體忽然破棺而出考赛,到底是詐尸還是另有隱情,我是刑警寧澤莉测,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布颜骤,位于F島的核電站,受9級(jí)特大地震影響捣卤,放射性物質(zhì)發(fā)生泄漏忍抽。R本人自食惡果不足惜八孝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸠项。 院中可真熱鬧干跛,春花似錦、人聲如沸祟绊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牧抽。三九已至嘉熊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扬舒,已是汗流浹背阐肤。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呼巴,地道東北人泽腮。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像衣赶,于是被迫代替她去往敵國和親诊赊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361