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();