Redisson源码-多线程之首个获取锁的线程加解锁流程
简介
当有多个线程同时去获取同一把锁时,第一个获取到锁的线程会进行加解锁,其他线程需订阅消息并等待锁释放。
以下源码分析基于redisson-3.17.6版本,不同版本源码会有些许不同需注意。
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.17.6</version>
</dependency>
当我们调用Redisson.lock()并且不设置锁时间时,我们进入RedissonLock的lock方法。
public void lock() {
try {
// -1L为锁时间,表示不限时
this.lock(-1L, (TimeUnit)null, false);
} catch (InterruptedException var2) {
throw new IllegalStateException();
}
}
private void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws InterruptedException {
// 获取当前线程id
long threadId = Thread.currentThread().getId();
// 尝试获取锁
Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
// lock acquired
// 获取到锁直接返回
if (ttl == null) {
return;
}
// 订阅锁消息:当锁被释放的时候,会通过publish发布一条消息,通知其它等待这个锁的线程,锁已经释放。
CompletableFuture<RedissonLockEntry> future = subscribe(threadId);
pubSub.timeout(future);
RedissonLockEntry entry;
if (interruptibly) {
entry = commandExecutor.getInterrupted(future);
} else {
entry = commandExecutor.get(future);
}
try {
// 不停尝试获取锁
while (true) {
ttl = tryAcquire(-1, leaseTime, unit, threadId);
// lock acquired
if (ttl == null) {
break;
}
// waiting for message
// 如果锁的过期时间>=0
if (ttl >= 0) {
try {
// 等待超时时间过去
entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
if (interruptibly) {
throw e;
}
entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
}
// 锁过期时间<0,代表锁的超时时间未设置
} else {
if (interruptibly) {
entry