Redisson分布式锁源码-可重入锁的八大机制-下(2)

Redisson分布式锁源码-可重入锁的八大机制-下(2)

可重入锁释放锁的场景

    (1)客户端宕机导致锁释放
    这个比较好理解一点,如果Redisson客户端刚加锁成功,此时后台肯定就有一个后台watchdog的定时任务每隔10s检查key,key如果存在就为它
 自动续期30s,当watchdog定时任务存在的情况下,如果不是主动释放锁,那么key将会一直的被watchdog这个定时任务维持加锁。
    如果客户端宕机了,此时watchdog定时任务当然也就是没了,既然没有了定时任务定时的为key续期,那么过完了30s之后,key自动就会被删除、
 key对应的锁也就释放了。
 
 客户端主动释放锁
 当客户端主动释放锁时,就会调用unlock方法,如下图所示:

在这里插入图片描述

跟进去看下底层的调用逻辑:

在这里插入图片描述

和上锁逻辑一样,释放锁的逻辑也是通过lua脚本来完成的,通过方法后面的参数我们可以知道:

KEYS[1]=anyLock
ARGV[2]=30000
ARGV[3]=UUID:ThreadId

第一个if中,redis.call(‘exists’,KEYS[1])==0 ,如果发现key不存在,发布订阅机制就会发布一些东西,这些和redis相关的订阅发布机制可暂时忽略;key此时当然是存在的,if分支跳过;

第二个if中,redis.call(‘hexists’,KEYS[1],ARGV[3])==0 ,如果发现key对应hash数据结构中、当前线程不存在或没有当前线程的信息,直接就返回了;此时key对应的hash数据结构中当然有当前线程的信息啊,跳出if分支;

然后通过命令:

hincrby KEYS[1] ARGV[3] -1,即 hincrby anyLock UUID:ThreadId -1

这里表示将线程UUID:ThreadId线程对key加锁的重入次数减1,即:

anyLock: {
UUID:ThreadId 2
}

变为

anyLock: {
UUID:ThreadId 1
}

此时,如果当前线程对这个key的重入锁次数counter还大于0,就表示当前线程对这个key不止加过一次锁,此时当然就不能删掉key啊,就执行redis.call(‘pexpire’,KEYS[1],ARGV[2]), 重置下key的存活时间为30s;
如果当前线程对这个key的重入锁次数counter等于0了,表示当前线程只对这个key加过一次锁,现在刚好释放一次锁,线程对该key已经没有加锁记录了,当然就直接执行redis.call(‘del’,KEYS[1])删除了;
这样也比较合理,因为如果说一个线程对一个key重入好几次锁,你只调用了一次unlock方法,就把别人key给删除了,那要重入锁又有什么意义呢。

释放锁和加锁其实是呼应的,你既然加锁是在key的hash数据结构中添加当前信息的记录,那释放锁当然也就是加锁的逆向操作了,包括锁重入次数的递增、key的删除等。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值