redis面试(十四)公平锁可重入

15 篇文章 0 订阅

可重入

就是当前线程多次加锁
while true,lindex redisson_lock_queue:{anyLock} 0,获取队列第一个元素,判断一下他的timeout时间是否大于当前时间了,假设当前时间是10:00:08,此时肯定是是不成立的,假设就直接跳出死循环

当前锁是否不存在,不成立;hexists anyLock UUID_01:threadId_01,在anyLock hash中,是否存在一个UUID_01:threadId_02的key,当前这个锁是否是客户端A加锁,成立,hincrby给加锁次数累加1,重新pexpire刷新锁key的生存时间为30000毫秒,返回一个nil

此时可重入加锁成功,无非就是累加了1次加锁的次数

分数刷新

在排队中的客户端,模拟等待一段时间后,再次尝试加锁。

第二个线程第二次尝试加锁

客户端B,10:00:00,10:00:15,他来再次尝试进行加锁,但是客户端A此时还是持有着这把锁的,此时会出现什么情况呢?

while true,获取队列第一个元素,同时获取这个元素的timeout时间,10:00:25 <= 10:00:15?不成立,while死循环退出

判断一下是否没人加锁,以及判断是否是客户端B进行的加锁,都不成立

ttl = 10:00:25 - 10:00:15 = 10000毫秒
timeout =10000毫秒 + 10:00:15 + 5000毫秒 = 10:00:30

zadd redisson_lock_timeout:{anyLock} 10:00:30 UUID_02:threadId_02,刷新一下有序集合中的元素的分数,10:00:30

大致可以理解为,你的某个客户端不是在不断的重试尝试加锁么?每次重试尝试加锁的时候,就判定为是这个客户端一次新的尝试加锁的行为,此时会将这个客户端对应的timeout时间往后延长,10:00:25,这次他重试加锁之后,timeout时间算出来就变成10:00:30,把这个客户端的timeout时间延长了,有序集合中的分数变大了

if redis.call(‘zadd’, KEYS[3], timeout, ARGV[2]) == 1 then

zadd指令的返回值,如果是第一次往里面怼入一个元素,返回值是什么?如果是第二次刷新这个元素的分数,返回值是什么?如果是第一次插入一个元素在有序集合中,此时就会返回值是1,同时会入队;但是后续不断的尝试加锁的时候,其实是会不断的刷新这个有序集合中的元素的分数,越来越大,但是每次刷新分数,返回值是0

所以不会重复的往队列中插入这个元素的

第三个线程第二次尝试加锁

客户端C,10:00:20,再次尝试加锁

10:00:30 < 10:00:20?不成立;尝试加锁,都不成立

再次刷新他的timeout分数

ttl = 10:00:30 - 10:00:20 = 10000毫秒
timeout = 10000毫秒 + 10:00:20 + 5000毫秒 = 10:00:35

zadd redisson_lock_timeout:{anyLock} 10:00:35 UUID_03:threadId_03

还是维持着跟之前一样的这么一个顺序,客户端B的分数会刷大,客户端C的分数其实也在不断的刷大,所以在有序集合中的分数的大小的顺序,基本上还是按照的是最初他们是如何排队的,此时也会如何排队

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木小同

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值