主要介绍Redisson可重入锁,实现可可重入加锁的源码解析
源码分析
这里回头看看加锁的代码如下
<T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
internalLockLeaseTime = unit.toMillis(leaseTime);
return evalWriteAsync(getName(), LongCodec.INSTANCE, command,
"if (redis.call('exists', KEYS[1]) == 0) then " +
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return nil; " +
"end; " +
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return nil; " +
"end; " +
"return redis.call('pttl', KEYS[1]);",
Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId));
}
其中lua脚本中的第二个分支
//如果当前线程已经获取到锁
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1)
then "
//将锁表示的对象的值,进行 加1
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
//设置锁的过期时间为 internalLockLeaseTime leaseTime(默认为30000毫秒)
"redis.call('pexpire', KEYS[1], ARGV[1]); " + "return nil; " +
这里回过头看redisson加锁实现的hash数据结构
此时的value的值1, 就是和锁的可重入有关,表示持有锁的线程对当前锁的重入次数
测试demo
这里执行一段代码测试下Reddsson可重入锁。同时观察下Redis中value值的变化
@ApiOperation(value="redis可重入锁测试")
@GetMapping(value = "/reentrantTest")
public BaseOutput<?> redisDemo(){
log.info("当前线程Id:{}",Thread.currentThread().getId());
RLock lock = redissonClient.getLock("lock");
log.info("第1次加锁");
lock.lock();
log.info("第2次加锁");
lock.lock();
log.info("第1次释放锁");
lock.unlock();
log.info("第2次释放锁");
lock.unlock();
return BaseOutput.success();
}
1.第一次加锁redis value值为1
2.第二次加锁redis value值为2
3.第一次释放锁,value值减一,value为1
4.第二次释放锁,value值减一,锁完全释放,redis key被删除