Redisson实现了一整套JDK中ReentrantLock的功能,这里对比一下实现的差异和核心的思想。

unfair模式的tryLock

ReentrantLock

①判断当前的state是否是0(初始状态),并用原子操作设置state,成功说明获取锁,并把当前线程设置为获取锁的线程。

②如果state不是0,检查当前线程是否是持有锁的线程,如果是就按照重入语义,增加计数,当然前提是不能超过最多重入的次数(不能溢出),然后将最终计数设置到state中。

③如果既不是①也不是②,那么tryLock失败。

Redisson

因为这里的锁是用Redis实现的,不在Java虚拟机内,所以只能用线程id来辨识锁,无法通过调用Thread.currentThread()方法来做。无参的加锁方法,leaseTime是-1,所以走的是if下面的逻辑,这个加锁的逻辑是通过lua脚本来完成的。这个和ReentrantLock的加锁方式不同的是,为了防止死锁产生(参考上一篇博客),这里设置了一个看门狗,默认时间是30秒钟,如果业务没有处理完,会每隔10秒钟延长这个锁的时间。

具体加锁的逻辑是通过lua脚本来完成,因为lua脚本会保证原子性。具体的lua脚本内容可以参见博客:https://my.oschina.net/u/2313177/blog/1919810。

Lua脚本中的执行分为以下三步:

①'exists', KEYS[1]) == 0 //exists检查redis中是否存在当前要获取的锁

('hset', KEYS[1], ARGV[2], 1) //如果不存在,则获取成功;同时设置锁名称KEYS[1],线程id[ARGV[2],锁重入次数1

('hexpire', KEYS[1], ARGV[1]) 设置锁的过期时间为ARGV[1],返回;

②('hexists', KEYS[1], ARGV[2]) ==1  //如果检查到存在KEYS[1],[ARGV[2],则说明获取成功

('hincrby', KEYS[1], ARGV[2], 1)  //此时会自增对应的value值,记录重入次数

('hexpire', KEYS[1], ARGV[1]) //并更新锁的过期时间

③key不存在

('pttl', KEYS[1] ) //直接返回key的剩余过期时间

上述一系列操作都是原子性的,所以没有线程并发问题。

后面还有一段添加listener的操作,因为上面的lua脚本执行的redis指令是异步的调用,会返回一个future,这个future如果成功放回,同时返回的结果的Boolean值是true,说明获取锁成功了,这个时候会调用一个叫做scheduleExpirationRenewal的方法:

如果该锁已经添加过了,那么返回,否则创建一个延时任务,该任务递归调用该任务本身。最后为了保证竞态,防止多个线程同时写,会将写失败的线程对应的任务cancel掉。这个方法的内容在上一篇博客中已经解释了,就是redisson看门狗的作用。

这里有几个问题需要注意一下:

①为什么说这里的返回值Boolean是true,就说明获取锁成功呢?

这里看下redis指令最后的一个commands参数:

结果的Boolean表示的是,返回值不等于null这个条件是否为真。这里如果Boolean是true,说明返回值是null。那么什么情况返回值是null呢?看上面分析的lua脚本,只有当当前线程id获取锁成功的时候,才会返回null,否则会返回ttl。

②tryAcquireAsync和tryAcquireOnceAsync

仔细看的话,会发现tryAcquireAsync中的判断是否加锁成功的逻辑和上述逻辑正好相反,

原因是因为这里的commands是

所以返回的就是指令本身,那么根据上述lua脚本,只有当获取锁的时候,返回值才是null,所以这里的判断虽然和上面相反,但是逻辑本身是一模一样的。

设计成这样的原因是因为,带once的方法需要返回Boolean,一锤子买卖,如果try失败了再进行其他逻辑。而后面的方法,失败后会进行复杂的锁竞争处理(这个后面会继续说)。

两者实现的功能从接口上也能看出不同,前者是:

失败就失败了,继续按照失败或成功来进行业务逻辑即可。

后者是:

如果没有立刻获取到锁,会在超时时间之内进行重试等复杂操作,直到获取锁或者超时为止。

Redisson(2-1)分布式锁实现对比 VS Java的ReentrantLock之tryLock相关推荐

  1. Redisson(2-2)分布式锁实现对比 VS Java的ReentrantLock之带超时时间的tryLock

    Redisson实现了一整套JDK中ReentrantLock的功能,这里对比一下实现的差异和核心的思想. unfair模式的带超时时间的tryLock(超时时间) ReentrantLock 这里上 ...

  2. Redisson(2-3)分布式锁实现对比 VS Java的ReentrantLock的FairLock

    Redisson实现了一整套JDK中ReentrantLock的功能,这里对比一下公平锁(Fair)实现的差异和核心的思想. 公平锁存在的意义是为了保证绝对的公平,但是有其弊端,这个在网上有很多相关的 ...

  3. redis分布式锁与zk分布式锁的对比

    在分布式环境下,传统的jvm级别的锁会失效,那么分布式锁就是非常有必要的一个技术,一般我们可以通过redis,zk等技术来实现我们的分布式锁 redis实现分布式锁: 原理:我们都知道redis的处理 ...

  4. Redisson实现Redis分布式锁的N种姿势

    点击蓝色"程序猿DD"关注我哟 来源:阿飞的博客 前几天发的一篇文章<Redlock:Redis分布式锁最牛逼的实现>,引起了一些同学的讨论,也有一些同学提出了一些疑问 ...

  5. springboot整合redisson实现多种分布式锁

    Redisson概述 Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid).它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式 ...

  6. 若依集成redisson实现redis分布式锁

    Redisson是Redis服务器上的分布式可伸缩Java数据结构----驻内存数据网格(In-Memory Data Grid,IMDG).底层使用netty框架,并提供了与java对象相对应的分布 ...

  7. RedisSon高并发分布式锁实战RedisSon源码解读

    Redis高并发分布式锁实战 1.分布式场景下的synchronized失效的问题–用redis实现分布式锁 synchronized是通过monitor实现的jvm级别的锁,如果是分布式系统,跑在不 ...

  8. Mysql学习总结(83)——常用的几种分布式锁:ZK分布式锁、Redis分布式锁、数据库分布式锁、基于JDK的分布式锁方案对比总结

    一.基于数据库实现分布式锁 1.1.悲观锁 利用select - where - for update 排他锁.注意: 其他附加功能与实现一基本一致,这里需要注意的是"where name= ...

  9. java分布式_分布式锁的四种JAVA实现方式

    前言 作为这一段时间学习分布式锁的总结,本文总结了四种Java分布式锁的实现方式,简单编写了代码,进行模拟实现.相关代码存放在我的github仓库. 为什么要用锁 系统内,有多个消费者,需要对同一共享 ...

最新文章

  1. 【原】iOS学习之Quartz2D(1)
  2. PAT甲级1015 Reversible Primes :[C++题解]进制位、秦九韶算法、判质数
  3. jenkins自动化打包部署,jenkins执行sh脚本不退出问题
  4. 大唐电信[600198]股票
  5. 解决Charles Response 中文乱码
  6. 线性分类器(Linear Classifier)
  7. 新概念第二册 Lesson 1 句子 结构 分析
  8. ​LeetCode刷题实战510:二叉搜索树中的中序后继 II
  9. 给C盘减减肥,让你电脑飞一般速度
  10. [MP3]MP3固件持续分享(2019.1.25)
  11. 用Python写一个最简单的计时秒表
  12. 基于JavaWeb的影视创作论坛的设计与实现/影视系统
  13. 2020年数据标注行业回顾及2021年展望
  14. 玲珑杯 1032 A-B
  15. 服务器操作系统查询命令行,服务器操作系统查看命令行
  16. Format函数的用法
  17. java 图片格式转化 wmf,emf 转 svg,png
  18. 复盘2020全球旅游业:新冠疫情巨大冲击下的艰难复苏
  19. 谷歌浏览器实现多开,单独cookie
  20. 遇见逆水寒最新服务器是哪个,遇见逆水寒合服公告 遇见逆水寒旧服账号还在吗...

热门文章

  1. 一种改版后检查硬件PCB生产资料的方法***-----Gerber对比,检查的方法
  2. alios thing 信号量_信号量_AliOS Things内核_API参考文档_AliOS Things 文档_IoT物联网操作系统 - 阿里云...
  3. 011 dilate(膨胀)、erode(腐蚀)
  4. c语言kbhit函数6,C语言中kbhit()函数怎么复位
  5. 应运而生的环保APP
  6. 拉格朗日乘数法(Lagrange multiplier)
  7. 连续办了16年,为什么阿里坚持搞集体婚礼?
  8. 域控服务器怎么开策略,组策略(域和域服务的搭建)
  9. 《疯狂Java讲义》读书笔记(七):Swing编程
  10. The road to learning English-Grammar