實操Redission 分布式鎖和同步器

1. 可重入鎖(Reentrant Lock)

概念:所謂重入鎖,指的是以線程為單位,當(dāng)一個線程獲取對象鎖之后,這個線程可以再次獲取本對象上的鎖,而其他的線程是不可以的

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

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

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

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

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

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

Redisson同時還為分布式鎖提供了異步執(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對象完全符合Java的Lock規(guī)范。也就是說只有擁有鎖的進程才能解鎖,其他進程解鎖則會拋出IllegalMonitorStateException錯誤。但是如果遇到需要其他進程也能解鎖的情況,請使用分布式信號量Semaphore 對象.

2. 公平鎖(Fair Lock)

概念:每個線程搶占鎖的順序為先后調(diào)用lock方法的順序依次獲取鎖,類似于排隊吃飯

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

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

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

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

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

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

Redisson同時還為分布式可重入公平鎖提供了異步執(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對象可以將多個RLock對象關(guān)聯(lián)為一個聯(lián)鎖,每個RLock對象實例可以來自于不同的Redisson實例。

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

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

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

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

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 給lock1,lock2,lock3加鎖,如果沒有手動解開的話,10秒鐘后將會自動解開
lock.lock(10, TimeUnit.SECONDS);

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

4.紅鎖(RedLock)

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

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

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

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

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

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 給lock1,lock2,lock3加鎖,如果沒有手動解開的話,10秒鐘后將會自動解開
lock.lock(10, TimeUnit.SECONDS);

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

5. 讀寫鎖(ReadWriteLock)

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

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

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

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

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

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

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

6.信號量(Semaphore)

基于Redis的Redisson的分布式信號量(Semaphore)Java對象RSemaphore采用了與java.util.concurrent.Semaphore相似的接口和用法。同時還提供了異步(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. 可過期性信號量(PermitExpirableSemaphore)

基于Redis的Redisson可過期性信號量(PermitExpirableSemaphore)是在RSemaphore對象的基礎(chǔ)上,為每個信號增加了一個過期時間。每個信號可以通過獨立的ID來辨識,釋放時只能通過提交這個ID才能釋放。它提供了異步(Async)、反射式(Reactive)RxJava2標(biāo)準(zhǔn)的接口。

RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");
String permitId = semaphore.acquire();
// 獲取一個信號,有效期只有2秒鐘。
String permitId = semaphore.acquire(2, TimeUnit.SECONDS);
// ...
semaphore.release(permitId);

8. 閉鎖(CountDownLatch)

基于Redisson的Redisson分布式閉鎖(CountDownLatch)Java對象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)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容