[分散式鎖] [Redisson實現] -誤解-- 對lock方法的使用
阿新 • • 發佈:2021-10-09
前言
看了很多用
redisson
實現分散式鎖的部落格, 對他們使用的方式我個人認為有一點點自己的看法, 接下來本文將以例子來驗證為什麼會有誤解, 和看看正確的方式應該怎麼寫?
本文原始碼: 原始碼下載
大多數認為的寫法
看到很多人都是這樣寫
RLock lock = redisson.getLock(KEY);
lock.lock()
// do your own work
lock.unlock()
簡單看完原始碼後, 我看到該方法會去呼叫一個響應一箇中斷的
lockInterruptibly
,此時我就有點疑惑了, 響應中斷就是表示執行緒如果發生中斷就不會在等待佇列中等待(當然redisson
是採用SUB/PUB
的方式),(本文不分析原始碼哈,對該鎖的原始碼分析會放到專門部落格裡面分析, 主要是驗證該如何使用)可以看下圖:
圖片.png
上圖中
lock
等方法會最終呼叫public void lockInterruptibly(long leaseTime, TimeUnit unit) throws InterruptedException
該方法會丟擲異常, 然而lock
方法並沒有把這個異常丟擲給使用者, 而是採用捕獲異常,並且重新設定中斷狀態.
這下就有點明白了, 是不是需要使用者自己來判斷當前執行緒的狀態來判斷當前執行緒是否獲得鎖了呢?已經猜到這一步了, 接下來就需要驗證一下自己的猜想
例子1:驗證上面的寫法
我是用
maven
專案構建的一個小專案,因此加入如下依賴
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.7.0</version>
</dependency>
加入以下例子.
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.config.Config;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class TestDistributedRedisLock {
private static CountDownLatch finish = new CountDownLatch(2);
private static final String KEY = "testlock";
private static Config config;
private static Redisson redisson;
static {
config = new Config();
config.useSingleServer().setAddress("127.0.0.1:6379");
redisson = (Redisson)Redisson.create(config);
}
public static void main(String[] args) {
Thread thread_1 = new LockWithoutBoolean("thread-1");
Thread thread_2 = new LockWithoutBoolean("thread-2");
thread_1.start();
try {
TimeUnit.SECONDS.sleep(10); // 睡10秒鐘 為了讓thread_1充分執行
thread_2.start();
TimeUnit.SECONDS.sleep(10); // 讓thread_2 等待鎖
thread_2.interrupt(); // 中斷正在等待鎖的thread_2 觀察thread_2是否會不會拿到鎖
finish.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
redisson.shutdown();
}
}
static class LockWithoutBoolean extends Thread {
private String name;
public LockWithoutBoolean(String name) {
super(name);
}
public void run() {
RLock lock = redisson.getLock(KEY);
lock.lock(10, TimeUnit.MINUTES);
System.out.println(Thread.currentThread().getName() + " gets lock. and interrupt: " + Thread