Redisson的可重入锁(Reentrant Lock)是基于Redis实现的分布式锁。

用于在分布式系统中提供线程安全的锁机制。它允许同一个线程在不释放锁的情况下多次获得锁,并在所有锁操作完成后,锁才真正被释放。

1.基本原理

可重入锁的核心思想是,同一线程可以多次获取同一个锁,且只有当所有锁释放操作都完成后,锁才会真正释放。

锁的可重入特性

Redisson通过维护一个计数器来实现锁的可重入特性。

锁的释放操作

锁的释放操作需要确保只有持有锁的线程才能释放锁。Redisson会在释放锁时检查Redis中存储的与当前线程的ID是否匹配,确保线程安全。

释放锁的Lua脚本逻辑:如果当前线程ID与Redis中保存的线程ID相同,则检查计数器的值。如果计数器减为0,删除锁;否则,只减少计数器值。

-- 如果Redis中存储的锁的持有者与当前线程的标识符相等(ARGV[1]),则进行解锁操作
if redis.call('get', KEYS[1]) == ARGV[1] then
    -- 尝试递减计数器(KEYS[2]为计数器的Key),表示释放一次锁
    if redis.call('decr', KEYS[2]) == 0 then
        -- 如果计数器减为0,说明锁完全释放,删除锁的Key
        return redis.call('del', KEYS[1])
    else
        -- 如果计数器未减为0,返回0表示锁未完全释放,暂时不删除锁
        return 0
    end
else
    -- 如果当前线程标识不匹配,说明不是该线程持有的锁,返回0表示无法解锁
    return 0
end

2.关键机制

为了防止死锁,Redisson为锁设置了过期时间。
如果持有锁的线程因为意外情况(如崩溃、网络分区等)未能及时释放锁,Redis会在锁的过期时间后自动释放,防止锁长时间占用资源。
Redisson提供了Watchdog机制,用于动态延长锁的有效期。默认情况下,Redisson的锁在过期之前,会通过看门狗定期检查线程的状态:

如果线程仍然在持有锁(即线程还在运行且没有释放锁),看门狗会自动延长锁的过期时间,防止锁过早释放。
默认的看门狗延时是30秒,Redisson会在锁的持有期间不断续期。
Redisson使用了Redis的Lua脚本来执行锁的加锁、释放等操作。
Lua脚本在Redis中具有原子性,这意味着即使在分布式环境下,这些操作也不会受到并发影响,从而保证了锁的安全性和一致性。

3.Redisson 可重入锁的代码示例

RLock lock = redissonClient.getLock("myLock");
 
try {
    // 尝试加锁,最多等待10秒,上锁以后20秒自动解锁
    boolean isLocked = lock.tryLock(10, 20, TimeUnit.SECONDS);
    
    if (isLocked) {
        // 执行业务逻辑
    }
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    if (lock.isHeldByCurrentThread()) {
        lock.unlock();  // 释放锁
    }
}

4.MultiLock

原理解析

可重入性:

超时和看门狗机制:

具体实现过程