redis面试(九)锁重入和互斥

可重入

1)如果一开始这个锁是没有的,第一次来加锁,这段lua脚本会如何执行?

"if (redis.call('exists', KEYS[1]) == 0) then " +

"redis.call('hset', KEYS[1], ARGV[2], 1); " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return nil; " +

"end; " +

一开始这个锁如果没有,第一次加锁,会进这个if then分支,hset设置一个hash的数据结构,pexpire设置这个key的生存时间,直接返回nil,也就是已给null,这个lua脚本后面的内容其实就不会执行了

如果Future拿到了那个lua脚本执行成功后的返回值之后,就会触发一个监听器

这是我们前面梳理过的逻辑

2)如果是在一个客户端的一个线程内,先对一个lock进行了加锁,然后后面又加了一次锁,形成了一个叫做可重入锁的概念,就同一个线程对一个lock可以反复的重复加锁多次,每次加锁和一次释放锁必须是配对的

第二次过来加锁的时候

"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; " +

hexists 命令,如果是查询的这个数据存的话,就返回"1"

那么这个判断会看到锁已经存在,下面的逻辑就给这个值+1 ,不断地+1

那可以猜测,释放的时候也是要不断地-1,加了多少次,也要对应的释放多少次。

锁互斥

如果已经有一个客户端的线程对一个key加了锁,那么此时其他的线程或者是客户端如果也要对这个key加锁,是如何被阻塞住的呢?部署在其他机器上的服务实例,或者是部署在其他机器上的其他服务

还是这个lua脚本实现的,我们现在已经加了一个名为anyLock的锁,并且线程id假如说是2345-zxcv-1

那也就是说

现在已经redis里面已经有一个名为anyLock的map数组,并且里面有个键值对"2345-zxcv-1":1

这时候如果有其他的线程也想获取这个锁

先看第一个判断 "if (redis.call('exists', KEYS[1]) == 0)"

然后也是进入第二个判断 "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then"

这时候锁名称虽然一样,但是"2345-zxcv-1" 这个值可是每个线程都不一样的,所以会返回return redis.call('pttl', KEYS[1]) 也就是当前这个缓存的过期时间

那这里逻辑执行完之后,再会到上一层方法,这个里面有个ttlRemaining==null的判断,如果是null的话证明加锁成功,就要执行看门狗的逻辑进行锁的延迟维护;如果不为空的话,就是加锁失败,与上面我们分析的逻辑一致。

再回到更上一层看一下逻辑,这里也是,如果返回的ttl是null,则证明加锁成功,可以直接返回;

如果不为空就要执行下面的阻塞逻辑;

while中的逻辑意思就是,先获取一次这个锁,成功的话结束,不成功的话,等待一段时间,再次执行获取锁。

总结

锁的可重入就是在map中不断的+1

而锁的互斥就是通过map数据中的一个键,通过线程名称来进行不同的线程判断,如果不是当前线程的话,就不让+1。

相关推荐
聪明的笨猪猪2 小时前
Java Redis “Sentinel(哨兵)与集群”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
渣哥3 小时前
三级缓存揭秘:Spring 如何优雅地处理循环依赖问题
javascript·后端·面试
渣哥3 小时前
为什么几乎所有 Java 项目都离不开 IoC?Spring 控制反转的优势惊人!
javascript·后端·面试
前端赵哈哈3 小时前
Vue I18n 完整安装与使用指南
前端·vue.js·面试
长安城没有风4 小时前
从入门到精通【Redis】初识Redis哨兵机制(Sentinel)
java·数据库·redis·后端
绝无仅有4 小时前
某大厂跳动Java面试真题之问题与解答总结(五)
后端·面试·github
绝无仅有4 小时前
某大厂跳动Java面试真题之问题与解答总结(四)
后端·面试·github
渣哥5 小时前
事务崩了别怪数据库!三大核心要素没掌握才是根本原因
javascript·后端·面试
渣哥5 小时前
你以为自动开启?Spring 事务支持其实还需要这几步!
javascript·后端·面试
zym大哥大6 小时前
Redis-List
数据库·redis·缓存