lock.unlock();

调用unlock方法,往下追

@Override
public void unlock() {try {// 1. 执行异步解锁操作并同步等待结果// - 获取当前线程ID作为锁持有者标识// - unlockAsync()触发Lua脚本执行实际解锁// - get()方法阻塞直到异步操作完成get(unlockAsync(Thread.currentThread().getId()));} catch (RedisException e) {// 2. 异常处理:识别非法解锁场景if (e.getCause() instanceof IllegalMonitorStateException) {// 2.1 特殊处理:当前线程非锁持有者// - 通常在Lua脚本返回nil时触发// - 表示尝试释放未被当前线程持有的锁throw (IllegalMonitorStateException) e.getCause();} else {// 2.2 其他Redis异常(如连接问题)// - 网络中断、Redis宕机等场景throw e;}}// 3. 成功执行路径://   - Lua脚本返回0(重入锁部分释放)或1(完全释放)//   - 后台自动触发看门狗任务取消(完全释放时)
}

再往下追unlcokAsync这个异步方法
这里调用解锁方法unlockInnerAsync同样返回了RFutrue,当lua脚本执行完过后,RFutrue就会变成完成状态,回调用回调函数onComplete,lua脚本就是再unlockInnerAsync里执行的,我们接着往下追

@Override
public RFuture<Void> unlockAsync(long threadId) {// 创建异步结果对象,用于返回解锁操作最终状态RPromise<Void> result = new RedissonPromise<Void>();// 执行核心解锁操作(发送Lua脚本到Redis)RFuture<Boolean> future = unlockInnerAsync(threadId);// 注册回调函数处理解锁结果future.onComplete((opStatus, e) -> {// 关键步骤:无论解锁成功与否,都取消看门狗续期任务// 防止锁释放后继续续期(相当于"喂狗"操作停止)cancelExpirationRenewal(threadId);// 异常处理:Redis操作出错if (e != null) {result.tryFailure(e);  // 设置结果为失败并传递异常return;}// 非法状态检查:opStatus为null表示解锁失败// 常见原因:尝试释放非当前线程持有的锁if (opStatus == null) {// 构造详细的非法状态异常信息IllegalMonitorStateException cause = new IllegalMonitorStateException("attempt to unlock lock, not locked by current thread by node id: "+ id + " thread-id: " + threadId);result.tryFailure(cause);  // 设置结果为失败return;}// 解锁成功:设置结果为成功result.trySuccess(null);});// 返回异步结果对象return result;
}
protected RFuture<Boolean> unlockInnerAsync(long threadId) {return evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,-- 1. 验证锁持有者身份
if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;  -- 非持有者尝试解锁
end; -- 2. 减少重入计数
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); -- 3. 判断是否完全释放
if (counter > 0) then -- 3.1 未完全释放(重入场景)redis.call('pexpire', KEYS[1], ARGV[2]);  -- 更新过期时间return 0;  -- 返回未完全释放标识
else -- 3.2 完全释放redis.call('del', KEYS[1]);  -- 删除锁redis.call('publish', KEYS[2], ARGV[1]);  -- 发布解锁消息return 1;  -- 返回成功释放标识
end; return nil;  -- 默认返回(不会执行到这里)Arrays.asList(getName(), getChannelName()), LockPubSub.UNLOCK_MESSAGE, internalLockLeaseTime, getLockName(threadId));}

 再执行完过后回取消定时任务,我们追进去,这里设计到全局静态map EXPIRATION_RENEWAL_MAP 放一张流程图方便回忆这个map

void cancelExpirationRenewal(Long threadId) {// 从全局MAP获取EntryExpirationEntry entry = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (entry != null) {// 关键操作:移除线程记录entry.removeThreadId(threadId);// 检查是否完全释放if (entry.hasNoThreads()) {// 取消定时任务Timeout timeout = entry.getTimeout();if (timeout != null) {timeout.cancel();}// 从全局MAP移除EXPIRATION_RENEWAL_MAP.remove(getEntryName());}}
}

可以看到map存储的是锁的名称和entry对象 entry对象里面放入了线程id,所以释放的时候先从entry移除线程id,如果没有了线程id再从map里移除entry对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91024.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91024.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/91024.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

四、计算机组成原理——第4章:指令系统

目录 4.1指令系统 4.1.1指令集体系结构 4.1.2指令的基本格式 1.零地址指令 2.一地址指令 3.二地址指令 4.三地址指令 5.四地址指令 4.1.3定长操作码指令格式 4.1.4扩展操作码指令格式 4.1.5指令的操作类型 1.数据传送 2.算术和逻辑运算 3.移位操作 4.转移操作 …

RAG面试内容整理-检索器与生成器的解耦架构

在RAG系统中,检索器(Retriever)与生成器(Generator)的解耦架构是实现灵活高效的关键设计。所谓解耦,即将检索相关文档和生成答案两个步骤分开,由不同的模块或模型负责。这种架构带来的直接好处是模块独立优化:我们可以针对检索任务微调或更换检索模型,而不必影响生成模…

【2026毕业论文鸿蒙系统毕设选题】最新颖的基于HarmonyOS鸿蒙毕业设计选题汇总易过的精品毕设项目分享(建议收藏)✅

文章目录前言最新毕设选题&#xff08;建议收藏起来&#xff09;最新颖的鸿蒙毕业设计选题汇总100套易过的精品毕设项目分享毕设作品推荐&#x1f447;&#x1f447;&#x1f447;文未可免费咨询毕设相关问题&#xff0c;点赞留言可送系统源码&#x1f447;&#x1f447;&#…

超全!Linux 面试 100 题精选解析:网络篇|16 个 Linux 网络排查与配置必考题详解

网络&#xff0c;是 Linux 系统的神经系统。 一台服务器再强大&#xff0c;没有网络连接也如孤岛。尤其在实际运维与面试场景中&#xff0c;“网络相关的问题”是高频重灾区&#xff0c;比如&#xff1a; IP 配置错乱&#xff0c;连不上公网DNS 无响应&#xff0c;域名解析失败…

在 CentOS 上安装 FFmpeg

在 CentOS 上安装 FFmpeg 可以通过以下两种推荐方法实现&#xff08;以 CentOS 7/8 为例&#xff09;&#xff1a; 方法一&#xff1a;通过 RPM Fusion 仓库安装&#xff08;推荐&#xff09; # 1. 安装 EPEL 仓库 sudo yum install epel-release# 2. 启用 RPM Fusion 仓库 # C…

数据结构——图(一、图的定义)

一、图的定义1、什么是图&#xff1f;图G(V,E) 如图&#xff0c;无向图G顶点集V{,,...,}&#xff0c;用|V|表示图G的顶点个数如&#xff1a;V{A,B,C,D} ,|V|4边集E{(u,v)|uV, vV}&#xff0c; 用|E|表示图G的边的条数如&#xff1a;E{(u,v)|(A,B),(A,D),(A,C),(C,D)}&#xf…

Python 列表推导式与生成器表达式

Python 列表推导式与生成器表达式在 Python 中&#xff0c;列表推导式&#xff08;List Comprehension&#xff09;和生成器表达式&#xff08;Generator Expression&#xff09;是处理序列数据的高效工具。它们不仅能简化代码&#xff0c;还能提升数据处理的效率。本文将详细介…

XCF32PVOG48C Xilinx Platform Flash PROM

XCF32PVOG48C 是 Xilinx 公司推出的一款高容量、低功耗的 Platform Flash PROM&#xff08;平台闪存配置芯片&#xff09;&#xff0c;专为 Xilinx FPGA 和 CPLD 系列产品提供非易失性配置存储支持。凭借其 32 Mbit 的大容量与出色的系统兼容性&#xff0c;该芯片成为中高端 FP…

重复文件清理工具,附免费链接

链接:https://pan.baidu.com/s/1s_Zx1eHp5Y-XnbbGldIgvw?pwdkjex 提取码:kjex 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦

【Spring Boot 快速入门】二、请求与响应

目录请求响应请求Postman 工具简单参数请求实体参数请求数组集合参数日期参数JSON 参数路径参数响应请求响应 请求 Postman 工具 Postman 是一款功能强大的网页调试与发送网页 HTTP 请求的 Chrome 插件 作用&#xff1a;常用于进行接口测试 简单参数请求 原始方式 在原始的…

高并发系统技术架构

&#xff08;点个赞&#xff0c;算法会给你推荐更多类似干货 ~&#xff09; 口诀&#xff1a; CDN 扛静态&#xff0c;WAF 防恶意&#xff1b;验证码拦机器&#xff1b; Nginx 先限流&#xff0c;Sentinel 再熔断&#xff1b; Redis 扣库存&#xff0c;MQ 异步写&#xff1b; 对…

python任意模块间采用全局字典来实现借用其他类对象的方法函数来完成任务或数据通信的功能

我们在编写pthon代码时&#xff0c;模块间的数据通信主要采用以下几种方法&#xff1a;1、采用全局变量。所有模块都通过引用全局变量&#xff0c;通过本模块对此全局变量数据的修改值&#xff0c;其他模块也能访问并得到此全局变量的当前值&#xff0c;由于全局变量的不可控性…

linux 部署 flink 1.15.1 并提交作业

下载 1.15.1 https://flink.apache.org/downloads.html#apache-flink-1151 部署模式分类 会话模式应用模式单作业模式 1、会话模式 先启动一个集群&#xff0c;保持一个会话&#xff0c;然后通过客户端提交作业&#xff0c;所有作业都在一个会话执行&#xff1b; 会话模式适合规…

Redis数据量过大的隐患:查询会变慢吗?如何避免?

一、Redis数据过多引发的五大隐患&#xff08;附系统交互图&#xff09; #mermaid-svg-X83bpHUu830QXKUt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-X83bpHUu830QXKUt .error-icon{fill:#552222;}#mermaid-svg-…

网络与信息安全有哪些岗位:(3)安全运维工程师

安全运维工程师是企业安全防线的 “日常守护者”&#xff0c;既要确保安全设备与系统的稳定运行&#xff0c;又要实时监控潜在威胁&#xff0c;快速响应并处置安全事件&#xff0c;是连接安全技术与业务运营的关键角色。其核心价值在于通过常态化运维&#xff0c;将安全风险控制…

鱼皮项目简易版 RPC 框架开发(三)

本文为笔者阅读鱼皮的项目 《简易版 RPC 框架开发》的笔记&#xff0c;如果有时间可以直接去看原文&#xff0c; 1. 简易版 RPC 框架开发 前面的内容可以笔者的前面两个篇笔记 鱼皮项目简易版 RPC 框架开发&#xff08;一&#xff09; 鱼皮项目简易版 RPC 框架开发&#xff08;…

嵌入式Linux:注册线程清理处理函数

在 Linux 多线程编程中&#xff0c;线程终止时可以执行特定的清理操作&#xff0c;通过注册线程清理函数&#xff08;thread cleanup handler&#xff09;来实现。这类似于使用 atexit() 注册进程终止处理函数。线程清理函数用于在线程退出时执行一些资源释放或清理工作&#x…

【Git】Linux-ubuntu 22.04 初步认识 -> 安装 -> 基础操作

文章目录Git 初识Git 安装Linux-centosLinux-ubuntuWindowsGit 基本操作配置 Git认识工作区、暂存区、版本库添加文件 -- 场景一查看 .git 文件添加文件 -- 场景二修改文件版本回退撤销修改情况一&#xff1a;对于工作区的代码&#xff0c;还没有 add情况二&#xff1a;已经 ad…

轻量级音乐元数据编辑器Metadata Remote

简介 什么是 Metadata Remote (mdrm) &#xff1f; Metadata Remote 是一个基于 Web 的音频元数据编辑工具&#xff0c;旨在简化在无头服务器&#xff08;即没有图形用户界面的服务器&#xff09;上编辑音频文件的元数据。用户只需使用 Docker 和浏览器&#xff0c;无需复杂的…

免费使用|共享服务器上线RTX3080(20GB显存)

共享服务器也上架GPU啦 生物信息学中有很多用到GPU的场景&#xff0c;例如我们分享过的&#xff1a;利用GPU加速TensorFlow、部署本地DeepSeek&#xff0c;空间转录组学习手册合辑加速。因此多种GPU供大家选择&#xff1a;RTX5090、4080S、5070显卡上机。为了让此前的CPU服务器…