Redisson
类
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它提供了一系列的分布式Java对象和服务,包括集合、映射、锁、队列、分布式计算、发布/订阅消息系统等。
Redisson实现了RedissonClient
接口,这个接口定义了Redisson客户端应该具备的方法。通过实现这个接口,Redisson能够提供与Redis交互的各种功能。
静态代码块
static {
RedissonReference.warmUp();
}
这是一个静态代码块,它在类加载时执行。RedissonReference.warmUp()
方法用于预热Redisson的一些内部组件,以提高后续操作的效率。
属性
QueueTransferService queueTransferService
: 这是一个队列传输服务,用于在Redisson实例之间传输队列数据。它主要用于处理分布式队列的迁移和复制操作。EvictionScheduler evictionScheduler
: 这是一个驱逐调度器,用于管理Redisson中的过期键和自动清理任务。它确保过期的数据能够被及时清理,从而释放资源。WriteBehindService writeBehindService
: 这是一个写后服务,用于实现写后日志(Write-Behind Logging)功能。它允许将写操作异步地写入Redis,从而提高性能。ConnectionManager connectionManager
: 这是一个连接管理器,负责管理Redisson与Redis服务器之间的连接。它包括连接的创建、维护和关闭等操作。CommandAsyncExecutor commandExecutor
: 这是一个命令异步执行器,用于执行Redis命令。它支持异步操作,提高Redisson的处理能力。ConcurrentMap<Class<?>, Class<?>> liveObjectClassCache
: 这是一个并发映射,用于缓存实时对象(Live Object)的类信息。实时对象是Redisson提供的一种特性,它允许将Java对象的状态存储在Redis中。Config config
: 这是一个配置对象,用于存储Redisson的配置信息。它包括连接配置、线程池配置、序列化配置等。ConcurrentMap<String, ResponseEntry> responses
: 这是一个并发映射,用于存储Redis命令的响应条目。每个响应条目包含命令的执行结果和相关状态信息。
方法
public RLock getLock(String name) {
return new RedissonLock(this.commandExecutor, name);
}
getLock(String name)
方法是一个工厂方法,它用于创建并返回一个RLock
对象。
RedissonLock
是RLock
接口的具体实现,它依赖于commandExecutor
来执行Redis命令,从而实现锁的功能。
RedissonLock
类
RedissonLock
类是 Redisson 框架中的一个关键组件,它实现了 Java 的 java.util.concurrent.locks.Lock
接口,提供了一种分布式锁的实现。
类声明
public class RedissonLock extends RedissonBaseLock
RedissonLock
类继承自 RedissonBaseLock
类,这意味着它继承了基础锁的实现,并在此基础上添加了特定的功能。
注释说明
Distributed implementation of {@link java.util.concurrent.locks.Lock}
:这是一个分布式实现的注释,表明RedissonLock
是一个分布式环境下的锁实现。Implements reentrant lock.
:这个类实现了可重入锁,意味着同一个线程可以多次获取同一个锁,而不会被阻塞。Lock will be removed automatically if client disconnects.
:如果客户端断开连接,锁会被自动移除,这有助于防止死锁的发生。Implements a <b>non-fair</b> locking so doesn't guarantees an acquire order.
:这个类实现了非公平锁,不保证锁获取的顺序。非公平锁可能会让一些线程在等待队列中等待时获得锁的机会减少。
属性
protected long internalLockLeaseTime;
- 这是一个保护属性,表示锁的内部租约时间。在分布式锁中,这个时间用于设置锁在 Redis 中的过期时间,以防止锁永久占用。
protected final LockPubSub pubSub;
- 这是一个
LockPubSub
对象,用于订阅和发布锁相关的消息。它用于实现锁的监听和自动续租功能。
- 这是一个
final CommandAsyncExecutor commandExecutor;
- 这是一个
CommandAsyncExecutor
对象,用于执行 Redis 命令。它是 Redisson 中执行所有 Redis 操作的核心组件。
- 这是一个
功能特点
RedissonLock
实现了可重入锁,这意味着线程可以多次获取同一个锁而不会阻塞。- 它通过
LockPubSub
实现了锁的自动续租功能,即如果持有锁的线程仍在执行,锁会自动延长租约时间。 - 当客户端断开连接时,锁会被自动释放,这有助于防止因客户端故障而导致的死锁。
RedissonLock
实现了非公平锁,不保证锁的获取顺序,这可能导致某些线程在等待队列中等待的时间更长。
方法
lock()
方法
lock()
方法和lockInterruptibly()
方法实际调用的是lock(long leaseTime, TimeUnit unit, boolean interruptibly)
私有方法,参数不同。
![]() | ![]() |
---|
查看代码
private void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws InterruptedException {
long threadId = Thread.currentThread().getId();
Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
// lock acquired
if (ttl == null) {
return;
}
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
if (ttl >= 0) {
try {
entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
if (interruptibly) {
throw e;
}
entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
}
} else {
if (interruptibly) {
entry.getLatch().acquire();
} else {
entry.getLatch().acquireUninterruptibly();
}
}
}
} finally {
unsubscribe(entry, threadId);
}
// get(lockAsync(leaseTime, unit));
}
解析
lock
方法是 RedissonLock
类中用于获取锁的核心方法。它实现了分布式锁的获取逻辑,以下是该方法的详细执行流程:
方法签名
private void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws InterruptedException
参数
leaseTime
:锁的租约时间,即锁在 Redis 中保持有效的时间。unit
:租约时间的单位。interruptibly
:一个布尔值,表示当线程在等待锁时是否可以被中断。
执行流程
- 获取当前线程的 ID:java获取当前执行线程的 ID,以便后续操作能够识别不同的线程。
long threadId = Thread.currentThread().getId();
- 尝试获取锁:java调用
Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
tryAcquire
方法尝试获取锁。如果锁可用,tryAcquire
会返回null
,表示锁已被成功获取。如果锁不可用,则返回锁的剩余生存时间(TTL)。 - 锁获取成功:java如果
if (ttl == null) { return; }
tryAcquire
返回null
,则表示锁已被成功获取,方法直接返回。 - 订阅锁相关消息:java订阅锁的发布/订阅消息,以便能够收到锁释放的通知。
CompletableFuture<RedissonLockEntry> future = subscribe(threadId); pubSub.timeout(future);
subscribe
方法返回一个CompletableFuture
,表示订阅操作的完成。 - 等待订阅完成:java根据是否可中断,等待订阅操作完成并获取
RedissonLockEntry entry; if (interruptibly) { entry = commandExecutor.getInterrupted(future); } else { entry = commandExecutor.get(future); }
RedissonLockEntry
对象。 - 循环尝试获取锁:java进入一个无限循环,不断尝试获取锁。
while (true) { // ... 省略了之前的代码 }
- 再次尝试获取锁:java在循环内部再次尝试获取锁。
ttl = tryAcquire(-1, leaseTime, unit, threadId);
- 锁获取成功:java如果锁被成功获取(
if (ttl == null) { break; }
tryAcquire
返回null
),则退出循环。 - 等待锁释放通知:java根据锁的 TTL,等待锁释放通知。如果 TTL 大于等于 0,则尝试在指定时间内获取锁。如果 TTL 小于 0,则根据是否可中断来等待。
if (ttl >= 0) { entry.getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS); } else { if (interruptibly) { entry.getLatch().acquire(); } else { entry.getLatch().acquireUninterruptibly(); } }
- 退出循环后,取消订阅:java一旦锁被成功获取并退出循环,取消订阅锁的发布/订阅消息。
unsubscribe(entry, threadId);
异常处理
- 如果在等待锁的过程中线程被中断,并且
interruptibly
参数为true
,则会抛出InterruptedException
。
lock
方法通过不断尝试获取锁,并在无法获取锁时等待锁释放通知的方式,实现了分布式环境下的锁获取逻辑。它处理了锁的订阅和取消订阅,以及线程中断的情况,确保了锁的安全和有效获取。
tryAcquire
方法和续约流程
tryAcquire
方法
private Long tryAcquire(long waitTime, long leaseTime, TimeUnit unit, long threadId) {
return get(tryAcquireAsync0(waitTime, leaseTime, unit, threadId));
}
- 调用
tryAcquireAsync0
方法,获取一个RFuture<Long>
对象。 - 使用
get
方法同步等待RFuture
的结果,并返回锁的剩余生存时间(TTL)或null
(如果锁被成功获取)。
tryAcquireAsync0
方法
private RFuture<Long> tryAcquireAsync0(long waitTime, long leaseTime, TimeUnit unit, long threadId) {
return getServiceManager().execute(() -> tryAcquireAsync(waitTime, leaseTime, unit, threadId));
}
- 使用
getServiceManager().execute
方法异步执行tryAcquireAsync
方法。 tryAcquireAsync
方法的执行结果被封装成一个RFuture<Long>
对象。
tryAcquireAsync
方法
tryAcquireAsync
源码
private RFuture<Long> tryAcquireAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId) {
RFuture<Long> ttlRemainingFuture;
if (leaseTime > 0) {
ttlRemainingFuture = tryLockInnerAsync(waitTime, leaseTime, unit, threadId, RedisCommands.EVAL_LONG);
} else {
ttlRemainingFuture = tryLockInnerAsync(waitTime, internalLockLeaseTime,
TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
}
CompletionStage<Long> s = handleNoSync(threadId, ttlRemainingFuture);
ttlRemainingFuture = new CompletableFutureWrapper<>(s);
CompletionStage<Long> f = ttlRemainingFuture.thenApply(ttlRemaining -> {
// lock acquired
if (ttlRemaining == null) {
if (leaseTime > 0) {
internalLockLeaseTime = unit.toMillis(leaseTime);
} else {
scheduleExpirationRenewal(threadId);
}
}
return ttlRemaining;
});
return new CompletableFutureWrapper<>(f);
}
- 根据
leaseTime
是否大于 0,选择使用传递的leaseTime
或internalLockLeaseTime
调用tryLockInnerAsync
方法,尝试在 Redis 中获取锁。 tryLockInnerAsync
方法返回一个RFuture<Long>
对象,表示尝试获取锁的操作。- 使用
handleNoSync
方法处理无同步的情况,并返回一个新的CompletionStage<Long>
。 - 将
CompletionStage<Long>
转换为RFuture<Long>
,以便后续可以同步等待结果。 - 在
RFuture
的thenApply
方法中,如果锁被成功获取(ttlRemaining
为null
),则根据leaseTime
是否大于 0 来设置internalLockLeaseTime
或调用scheduleExpirationRenewal
方法来安排锁的续租。
scheduleExpirationRenewal
方法
源码
protected void scheduleExpirationRenewal(long threadId) {
ExpirationEntry entry = new ExpirationEntry();
ExpirationEntry oldEntry = EXPIRATION_RENEWAL_MAP.putIfAbsent(getEntryName(), entry);
if (oldEntry != null) {
oldEntry.addThreadId(threadId);
} else {
entry.addThreadId(threadId);
try {
renewExpiration();
} finally {
if (Thread.currentThread().isInterrupted()) {
cancelExpirationRenewal(threadId);
}
}
}
}
- 创建一个新的
ExpirationEntry
对象,并尝试将其放入EXPIRATION_RENEWAL_MAP
。 - 如果
EXPIRATION_RENEWAL_MAP
中已经存在该锁的ExpirationEntry
,则将当前线程的 ID 添加到该条目中。 - 如果是新创建的
ExpirationEntry
,则调用renewExpiration
方法来安排锁的续租任务。
renewExpiration
方法
源码
private void renewExpiration() {
ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());
if (ee == null) {
return;
}
Timeout task = getServiceManager().newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());
if (ent == null) {
return;
}
Long threadId = ent.getFirstThreadId();
if (threadId == null) {
return;
}
CompletionStage<Boolean> future = renewExpirationAsync(threadId);
future.whenComplete((res, e) -> {
if (e != null) {
log.error("Can't update lock {} expiration", getRawName(), e);
EXPIRATION_RENEWAL_MAP.remove(getEntryName());
return;
}
if (res) {
// reschedule itself
renewExpiration();
} else {
cancelExpirationRenewal(null);
}
});
}
}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);
ee.setTimeout(task);
}
- 从
EXPIRATION_RENEWAL_MAP
中获取锁的ExpirationEntry
。 - 如果
ExpirationEntry
不存在,则直接返回。 - 创建一个新的定时任务
TimerTask
,该任务会在internalLockLeaseTime / 3
时间后执行。 - 在
TimerTask
的run
方法中,获取ExpirationEntry
并检查是否需要续租锁。 - 使用
renewExpirationAsync
方法异步续租锁,并在完成后根据结果决定是否重新安排续租任务或取消续租。
执行流程总结
tryAcquire
方法被调用,以尝试获取锁。tryAcquireAsync0
方法异步执行tryAcquireAsync
方法。tryAcquireAsync
方法尝试在 Redis 中获取锁,并根据结果设置锁的租约时间或安排续租。- 如果锁被成功获取,
scheduleExpirationRenewal
方法被调用以安排锁的续租。 renewExpiration
方法创建一个定时任务,该任务定期续租锁,直到锁被释放或续租失败。
这个流程确保了分布式锁能够在获取后定期续租,以防止锁在持有期间过期。
RedissonMultiLock
类
这个类 RedissonMultiLock
是一个基于 Redisson 实现的分布式多锁管理器。
类的职责
RedissonMultiLock
的主要职责是管理多个独立的锁,并使它们表现得像一个单一的锁。当你需要同时锁定多个资源时,这个类非常有用。
在获取锁时,它会在所有给定的锁对象上尝试获取锁,并且只有在所有锁都成功时才认为锁被获取。
属性
final List<RLock> locks = new ArrayList<>();
这个属性是 RedissonMultiLock
的核心,它存储了构成多锁的所有独立的 RLock
对象。这些锁可以是来自不同 Redisson 实例的锁。
final
关键字表明 locks
属性在 RedissonMultiLock
实例创建后不可更改,这意味着一旦 RedissonMultiLock
被实例化,它所管理的锁列表就不能再被修改。
构造函数
RedissonMultiLock(RLock... locks)
: 构造函数接受多个RLock
对象作为参数,并将它们存储在一个列表中。
方法概览
锁操作
lock()
: 阻塞直到获取所有锁。lockInterruptibly()
: 与lock()
类似,但可被中断。tryLock()
: 尝试获取所有锁,立即返回,不阻塞。tryLock(long waitTime, TimeUnit unit)
: 在指定时间内尝试获取所有锁。unlock()
: 释放所有锁。
异步锁操作
lockAsync()
: 异步获取所有锁。tryLockAsync()
: 异步尝试获取所有锁。unlockAsync()
: 异步释放所有锁。
其他方法
newCondition()
: 不支持,会抛出UnsupportedOperationException
。isLocked()
: 检查是否持有所有锁。- 等等。
内部类
内部类 LockState
在 RedissonMultiLock
中扮演着关键角色,它封装了与多锁操作相关的状态和逻辑。
属性
newLeaseTime
: 如果设置了租约时间(leaseTime
),则newLeaseTime
是用来刷新锁租约的时间。如果等待时间(waitTime
)大于0,则newLeaseTime
是waitTime
的两倍;否则,它等于leaseTime
。lockWaitTime
: 获取单个锁时的等待时间,这个值是calcLockWaitTime(remainTime)
的结果。acquiredLocks
: 已经成功获取的锁的列表。waitTime
: 尝试获取锁的最大等待时间。threadId
: 当前线程的ID,用于确保锁的正确释放。leaseTime
: 锁的租约时间。unit
: 时间单位,用于waitTime
和leaseTime
。remainTime
: 剩余的等待时间,用于计算是否超时。time
: 记录当前操作开始的时间戳。failedLocksLimit
: 允许失败的锁的数量限制。
构造函数
LockState(long waitTime, long leaseTime, TimeUnit unit, long threadId)
: 构造函数初始化所有属性,并计算newLeaseTime
、lockWaitTime
和remainTime
。
方法
tryAcquireLockAsync(ListIterator<RLock> iterator)
: 异步尝试获取锁,这个方法会递归地尝试获取所有锁,直到成功或者达到失败锁的限制。它使用ListIterator
遍历锁列表,并对每个锁调用tryLockAsync
。- 如果没有更多的锁需要尝试,它会调用
checkLeaseTimeAsync
来刷新租约时间。 - 如果锁获取失败,它会检查是否达到了失败锁的限制,如果达到,它会释放已获取的锁并返回。
- 如果没有达到失败锁的限制,它会继续尝试获取下一个锁。
- 如果没有更多的锁需要尝试,它会调用
checkLeaseTimeAsync()
: 异步检查并刷新所有已获取锁的租约时间。如果leaseTime
大于0,它会为每个已获取的锁调用expireAsync
。checkRemainTimeAsync(ListIterator<RLock> iterator)
: 检查剩余的等待时间,如果超时,则释放已获取的锁并返回失败。如果没有超时,它会继续尝试获取下一个锁。
逻辑流程
- 初始化:创建
LockState
实例时,设置初始状态。 - 尝试获取锁:通过
tryAcquireLockAsync
方法,按顺序尝试获取锁。 - 处理失败:如果获取锁失败,根据
failedLocksLimit
决定是否重试或者放弃。 - 租约时间刷新:如果设置了租约时间,在所有锁都成功获取后,刷新租约时间。
- 超时处理:如果在指定的等待时间内没有成功获取所有锁,释放已获取的锁并返回失败。
LockState
内部类通过封装复杂的逻辑,使得 RedissonMultiLock
类的代码更加清晰和易于维护。它使用 Java 的 CompletableFuture
和 CompletionStage
来处理异步操作,确保了锁操作的原子性和正确性。
方法
lock()
方法
public void lock() {
try {
lockInterruptibly();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
lock
方法首先调用 lockInterruptibly
方法。
如果 lockInterruptibly
方法被中断,它会捕获 InterruptedException
并重新设置当前线程的中断状态。
查看代码
public void lockInterruptibly() throws InterruptedException {
lockInterruptibly(-1, null);
}
public void lockInterruptibly(long leaseTime, TimeUnit unit) throws InterruptedException {
long baseWaitTime = locks.size() * 1500;
while (true) {
long waitTime;
if (leaseTime <= 0) {
waitTime = baseWaitTime;
} else {
waitTime = unit.toMillis(leaseTime);
if (waitTime <= baseWaitTime) {
waitTime = ThreadLocalRandom.current().nextLong(waitTime/2, waitTime);
} else {
waitTime = ThreadLocalRandom.current().nextLong(baseWaitTime, waitTime);
}
}
if (tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS)) {
return;
}
}
}
如果 leaseTime
小于或等于0,设置 waitTime
为 baseWaitTime
,这是基于锁的数量计算出来的一个基础等待时间。
如果 leaseTime
大于0,计算 waitTime
为 unit.toMillis(leaseTime)
。
使用 ThreadLocalRandom.current().nextLong(start, end)
方法生成一个随机的等待时间,这个时间会在 waitTime
的基础上进行调整,以确保每次获取锁的时间不同。
进入一个无限循环,尝试获取锁。
如果成功获取锁,退出循环并返回。
如果获取锁失败,继续循环,每次循环都会重新计算 waitTime
并尝试获取锁。
查看代码
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
// 声明新租约时间变量,初始值为-1
long newLeaseTime = -1;
// 如果租约时间大于0
if (leaseTime > 0) {
// 如果等待时间大于0,则新租约时间为等待时间的两倍
if (waitTime > 0) {
newLeaseTime = unit.toMillis(waitTime) * 2;
} else {
// 否则,新租约时间等于租约时间
newLeaseTime = unit.toMillis(leaseTime);
}
}
// 获取当前系统时间
long time = System.currentTimeMillis();
// 声明剩余时间变量,初始值为-1
long remainTime = -1;
// 如果等待时间大于0,则设置剩余时间为等待时间
if (waitTime > 0) {
remainTime = unit.toMillis(waitTime);
}
// 计算锁等待时间
long lockWaitTime = calcLockWaitTime(remainTime);
// 获取失败锁的极限数量
int failedLocksLimit = failedLocksLimit();
// 创建一个已获取锁的列表
List<RLock> acquiredLocks = new ArrayList<>(locks.size());
// 遍历所有锁
for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) {
RLock lock = iterator.next();
// 声明变量,用于判断是否获取到锁
boolean lockAcquired;
try {
// 如果等待时间和租约时间都小于等于0,尝试获取锁而不等待
if (waitTime <= 0 && leaseTime <= 0) {
lockAcquired = lock.tryLock();
} else {
// 计算实际等待时间
long awaitTime = Math.min(lockWaitTime, remainTime);
// 尝试在指定时间内获取锁
lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);
}
} catch (RedisResponseTimeoutException e) {
// 如果发生Redis响应超时异常,释放已获取的锁并设置获取锁失败
unlockInner(Arrays.asList(lock));
lockAcquired = false;
} catch (Exception e) {
// 如果发生其他异常,设置获取锁失败
lockAcquired = false;
}
// 如果获取到锁,则添加到已获取锁的列表中
if (lockAcquired) {
acquiredLocks.add(lock);
} else {
// 如果失败的锁数量达到极限,则退出循环
if (locks.size() - acquiredLocks.size() == failedLocksLimit()) {
break;
}
// 如果失败锁的极限数量为0,则释放所有已获取的锁
if (failedLocksLimit == 0) {
unlockInner(acquiredLocks);
// 如果等待时间小于等于0,返回失败
if (waitTime <= 0) {
return false;
}
// 重置失败锁的极限数量并清空已获取锁的列表
failedLocksLimit = failedLocksLimit();
acquiredLocks.clear();
// 重置迭代器
while (iterator.hasPrevious()) {
iterator.previous();
}
} else {
// 否则,减少失败锁的极限数量
failedLocksLimit--;
}
}
// 如果剩余时间大于0,则更新剩余时间
if (remainTime > 0) {
remainTime -= System.currentTimeMillis() - time;
time = System.currentTimeMillis();
// 如果剩余时间小于等于0,释放所有已获取的锁并返回失败
if (remainTime <= 0) {
unlockInner(acquiredLocks);
return false;
}
}
}
// 如果租约时间大于0,则设置所有已获取锁的过期时间
if (leaseTime > 0) {
acquiredLocks.stream()
.map(l -> (RedissonBaseLock) l)
.map(l -> l.expireAsync(unit.toMillis(leaseTime), TimeUnit.MILLISECONDS))
.forEach(f -> f.toCompletableFuture().join());
}
// 如果所有锁都成功获取,则返回成功
return true;
}
unlock()
方法
RedissonRedLock
类
RedissonRedLock
继承自RedissonMultiLock
类,并用于实现Redisson框架中的红锁算法。
红锁算法的核心在于在多个独立的Redis节点上获取锁,以提高分布式系统中的锁的可用性和容错性。这个类的设计考虑了如何有效地处理多个锁的获取和释放,同时确保在大多数节点上成功获取锁。
在获取锁时,它会在所有给定的Redis节点上尝试获取锁,并且只有在大多数节点上成功时才认为锁被获取。
类定义
public class RedissonRedLock extends RedissonMultiLock {
这行代码定义了一个名为RedissonRedLock
的类,它继承自RedissonMultiLock
。这意味着RedissonRedLock
将继承RedissonMultiLock
的所有属性和方法。
构造方法
public RedissonRedLock(RLock... locks) {
super(locks);
}
构造方法接受一个可变参数RLock... locks
,这是一个RLock
对象数组,每个RLock
可以由不同的Redisson实例创建。通过调用super(locks)
,它将这个锁数组传递给父类的构造方法。
方法
failedLocksLimit()
@Override
protected int failedLocksLimit() {
return locks.size() - minLocksAmount(locks);
}
这个方法重写了父类中的failedLocksLimit
方法。它用于确定在尝试获取多个锁时,允许失败的锁的最大数量。计算方式是锁的总数减去minLocksAmount
方法返回的值。
minLocksAmount()
protected int minLocksAmount(final List<RLock> locks) {
return locks.size()/2 + 1;
}
这个方法计算获取锁成功所需的最小锁数量。算法是锁的总数除以2,然后加1。这是为了保证在多个Redis节点上获取锁时,大多数节点已经成功获取锁。
calcLockWaitTime()
@Override
protected long calcLockWaitTime(long remainTime) {
return Math.max(remainTime / locks.size(), 1);
}
这个方法用于计算在尝试获取每个锁时的等待时间。它将剩余时间除以锁的数量,并确保至少等待1毫秒。这是为了保证在尝试获取多个锁时,每个锁都有足够的时间尝试。
unlock()
@Override
public void unlock() {
unlockInner(locks);
}
这个方法重写了父类中的unlock
方法,用于释放所有已经获取的锁。它调用了一个名为unlockInner
的内部方法(可能是从父类继承的或在这个类的其他部分定义的),并将所有锁作为参数传递。
参考链接:
官网:https://github.com/redisson/redisson/wiki/Table-of-Content
https://cloud.tencent.com/developer/article/1862801
源码版本
xml<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.23.3</version> </dependency>