Redis如何实现可重入锁的设计


这篇文章主要介绍Redis如何实现可重入锁的设计,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!但是仍然有些场景是不满⾜的,例如⼀ 个⽅法获取到锁之后,可能在⽅法内调这个⽅法此时就获取不到锁了。这个时候我们就需要把锁改进成可 重⼊锁了。 重⼊锁,指的是以线程为单位,当⼀个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,⽽其 他的线程是不可以的。可重⼊锁的意义在于防⽌死锁。 实现原理是通过为每个锁关联⼀个请求计数器和⼀个占有它的线程。当计数为 0 时,认为锁是未被占有 的;线程请求⼀个未被占有的锁时,JVM 将记录锁的占有者,并且将请求计数器置为 1 。 如果同⼀个线程再次请求这个锁,计数将递增;每次占⽤线程退出同步块,计数器值将递减。直到计数器 为 0, 锁被释放。 关于⽗类和⼦类的锁的重⼊:⼦类覆写了⽗类的 synchonized ⽅法,然后调⽤⽗类中的⽅法,此时如果没有重⼊的锁,那么这段代码将产⽣死锁。代码演示不可重⼊不可重⼊锁
使用不可重入锁
当前线程执⾏ call() ⽅法⾸先获取 lock,接下来执⾏ inc() ⽅法就⽆法执⾏ inc() 中的逻辑,必须先释放锁。该例很好的说明了不可重⼊锁。可重入锁锁实现
锁使用可重⼊意味着线程可进⼊它已经拥有的锁的同步代码块。设计两个线程调⽤ call() ⽅法,第⼀个线程调⽤ call() ⽅法获取锁,进⼊ lock() ⽅法,由于初始 lockedBy 是 null,所以不会进⼊ while ⽽挂起当前线程,⽽是增量 lockedCount 并记录 lockBy 为第 ⼀个线程。接着第⼀个线程进⼊ inc() ⽅法,由于同⼀进程,所以不会进⼊ while ⽽挂起,接着增量 lockedCount,当第⼆个线程尝试 lock,由于 isLocked=true, 所以他不会获取该锁,直到第⼀个线程调⽤两次 unlock() 将 lockCount 递减为 0,才将标记为 isLocked 设置为 false。设计思路假设锁的key为“lock”,hashKey是当前线程的id:“threadId”,锁自动释放时间假设为20。判断lock是否存在 EXISTS lock不存在,则自己获取锁,记录重入层数为1.存在,说明有人获取锁了,继续判断是不是自己的锁,即判断当前线程id作为hashKey是否存在:HEXISTS lock threadId不存在,说明锁已经有了,且不是自己获取的,锁获取失败.存在,说明是自己获取的锁,重入次免费云主机域名数+1: HINCRBY lock threadId 1 ,最后更新锁自动释放时间, EXPIRE lock 20
判断当前线程id作为hashKey是否存在: HEXISTS lock threadId不存在,说明锁已失效存在,说明锁还在,重入次数减1: HINCRBY lock threadId -1 ,获取新的重入次数,判断重入次数是否为0,为0说明锁全部释放,删除key: DEL lock因此,存储在锁中的信息就必须包含:key、线程标识、重入次数。不能再使用简单的 key-value 结构, 这里推荐使用 hash 结构。而且要让所有指令都在同一个线程中操作,那么使用 lua 脚本。lua 脚本lock.luaunlock.lua在项目中集成编写 RedisLock 类以上是“Redis如何实现可重入锁的设计”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注百云行业资讯频道!

相关推荐: B站十年沉浮录:盈利困境阴云不散

6月份,B站在上海举办了自己的十周年庆典,逐渐成熟的B站影响力越来越大。B站十周年的微博话题下,曝光量48小时就达到了2.5亿的高峰,讨论量高达22.2万。《三体》动画化的消息更是点燃了全网,这个消息牢牢占据了各大社交平台热搜榜首。 十岁的B站,风华正茂。极高…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 01/03 22:41
下一篇 01/03 22:42