Bootstrap

redisson重入锁的原理

redisson重入锁的原理

什么是重入锁?

一个线程可以多次获取同一把锁。

为什么要使用同一把锁?

有很多的原型,这里我举一个例子。

在特殊的业务中,一个方法一调用方法二,两个方法调用之前需要获取这一把锁,如果锁获取不到之后需要等待,那么,调用方法一的时候获取这把锁,调用方法二的之后获取不到,这个时候就产生了死锁。

怎么设计重入锁?

这个不可重入锁

/**
 * @ClassName: SimpleRedisLock
 * @Description: 初级的redis分布式锁
 * @Author: csh
 * @Date: 2025-02-19 15:05
 */
public class SimpleRedisLock implements ILock{
    private StringRedisTemplate stringRedisTemplate;
    private String name;
    private static final String KEY_PREFIX = "lock:";
    private static final String UUID_PREFIX = UUID.randomUUID().toString(true)+"-";
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
    static{
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_SCRIPT.setResultType(Long.class);
    }


    public SimpleRedisLock(String name , StringRedisTemplate stringRedisTemplate ) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }


    /**
     * @param timeoutSec
     * @description: 尝试获取锁
     * @param: timeoutSec 锁过期时间
     * @return: boolean
     * @author: csh
     * @date: 2025/2/19
     */
    @Override
    public boolean tryLock(long timeoutSec) {

        // 获取线程提示
        String threadId = UUID_PREFIX + Thread.currentThread().getId();

        // 获取线程锁
        Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

    /**
     * @description: 释放锁
     * @param:
     * @return: void
     * @author: csh
     * @date: 2025/2/19
     */
    @Override
    public void unlock() {
        // 调用lua脚本
        stringRedisTemplate.execute(
                UNLOCK_SCRIPT,
                // 获取锁的key
                Collections.singletonList(KEY_PREFIX + name),
                // 获取线程id
                UUID_PREFIX + Thread.currentThread().getId()
        );
    }
}

自己定义的锁使用的是redis的setnx,只有在key不存在的情况下才能设置,意味着如果有线程获取到这把锁,后面的包括自己不能再次获取。

redisson实现了可重入锁,Rlock,实现的大概原理是,采用hash结构用来存储锁,其中大key表示表示这把锁是否存在,用小key表示当前这把锁被哪个线程持有,小key的值记录的同一线程获取锁的次数,同一个线程可以多次获取同一把锁,每次获取计数器加一。

实现原理如下:

获取:
在这里插入图片描述

释放:
在这里插入图片描述

;