前言
看了很多用
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() +