当前位置: 首页 > web >正文

【Redisson】锁可重入原理

目录

一、基本原理

二、源码解析:

(2)获取锁

(1)释放锁:


       

        之前给大家介绍过redisson的分布式锁,用redisson来实现比自己手搓简单的分布式锁有很多好处,因为这些可重入、可重试的逻辑较为复杂,他们的lua脚本不可能让我们在开发时自己实现,这样太耗时间了。所以redisson就帮我们实现了可重入和可重试。但我们也要知道他的原理,这期我们先讲可重入。


上一篇:

【Redisson】快速实现分布式锁-CSDN博客


一、基本原理

基本原理:

(1)获取锁的时候,还是使用setnx命令,如果该锁还没有被获取过,直接set,也就是获取锁成功

(2)当该线程第二次获取锁时,因为锁已经被获取了,也就是setnx返回false。这时候,先不直接返回获取锁失败的逻辑,而是先判断该锁的value值是不是自己,如果是,那么就获取锁成功。

(3)有一个计数器,每次获取锁成功计数器就+1,每次释放锁的时候计数器就-1。当计数器为0的时候表明该线程所有重入的锁都被释放完毕了,就可以删除这个key。那么其他线程就可以获取锁了

(4)因为key的value值既要记录线程标识,也要记录重入次数。所以String类型的结构就不满足了。需要使用到hash结构

(5)注意:每次释放锁时,如果value值不是0,说明该锁还是被该线程占用的。也就是释放重入锁的时候,要重置锁的有效期

图解:



二、源码解析:

(2)获取锁

<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {return this.commandExecutor.syncedEvalNoRetry(this.getRawName(), LongCodec.INSTANCE, command, "local mode = redis.call('hget', KEYS[1], 'mode');" +"   if (mode == false) then " +"       redis.call('hset', KEYS[1], 'mode', 'read');" +"       redis.call('hset', KEYS[1], ARGV[2], 1);" +"       redis.call('set', KEYS[2] .. ':1', 1);" +"        redis.call('pexpire', KEYS[2] .. ':1', ARGV[1]);" +"       redis.call('pexpire', KEYS[1], ARGV[1]);" +"       return nil;" +"   end;" +"   if (mode == 'read') or (mode == 'write' and redis.call('hexists', KEYS[1], ARGV[3]) == 1) then" +"        local ind = redis.call('hincrby', KEYS[1], ARGV[2], 1);" +"        local key = KEYS[2] .. ':' .. ind;redis.call('set', key, 1);" +"        redis.call('pexpire', key, ARGV[1]);" +"        local remainTime = redis.call('pttl', KEYS[1]);" +"        redis.call('pexpire', KEYS[1], math.max(remainTime, ARGV[1]));" +"        return nil;" +"   end;" + "return redis.call('pttl', KEYS[1]);",Arrays.asList(this.getRawName(), this.getReadWriteTimeoutNamePrefix(threadId)), new Object[]{unit.toMillis(leaseTime), this.getLockName(threadId), this.getWriteLockName(threadId)});}

解析:

(1)释放锁:

解析: 

http://www.xdnf.cn/news/13668.html

相关文章:

  • Redis初识第一期
  • 从0到1构建高并发秒杀系统:实战 RocketMQ 异步削峰与Redis预减库存
  • 接口测试常用工具及测试方法(基础篇)
  • 【MySQL】视图
  • 电话号码的字母组合
  • 12.ack,ACK 的区别与含义
  • 【项目实践】SMBMS(Javaweb版)(五)供应商管理模块
  • 时间同步技术在电力系统中的应用二
  • 现代建筑中空气流向管理系统SKGL的智能化趋势
  • 稳定币的监管
  • Agent应用案例精选,以及主流Agent框架开源项目推荐
  • 软件测试面试题总结【含答案】
  • 3.3.2 纠错编码(海明校验码)
  • web项目实现PWA和Browsersync的安装及使用方法
  • 锂电池3V\3.3V\3.7V升5V升压芯片,选型指南
  • 欧洲AI的崛起:Mistral推出首款逻辑推理模型Magistral,挑战美中AI霸主地位
  • UE5 学习系列(七)导入bridge资产包
  • 雷卯针对易百纳EB-SS528-DC-175开发板防雷防静电方案
  • 龙虎榜——20250611
  • 内核性能调优
  • 什么是分布式锁,及其实现
  • 洛谷 P2757 [国家集训队] 等差子序列
  • Spring | 深入解析 Spring AOP 中的AopProxyUtils.ultimateTargetClass()解决代理对象注解获取问题
  • Zero-Shot突变预测VenusREM的安装和使用
  • Office 365下载安装教程(超详细图文教程)从零开始的完整安装指南
  • python中的字符串、输入与输出、列表
  • 【更新至2024年】1992-2024年全国及各省地区生产总值、第一产业增加值、第二产业增加值、第三产业增加值、省GDP数据(无缺失)
  • MySQL:Prepared Statement 预处理语句
  • 表格里的图片链接怎么变成图片【附工具+源码演示】
  • 鴻蒙app開發中如何 使用 shift+ctrl+f 快捷搜索