0

0

如何在Java中编写可中断的锁获取逻辑_lockInterruptibly方法响应外界终止信号实战

P粉602998670

P粉602998670

发布时间:2026-03-10 12:57:11

|

544人浏览过

|

来源于php中文网

原创

lockinterruptibly能响应中断而lock不能,因前者将中断作为退出条件立即抛异常,后者屏蔽中断直至获锁;需配合try-catch-finally确保unlock,且仅对未持锁线程有效。

如何在java中编写可中断的锁获取逻辑_lockinterruptibly方法响应外界终止信号实战

lockInterruptibly 为什么能响应中断而 lock 不能

因为 lock() 是个“死磕型”操作:线程一旦开始抢锁,就彻底屏蔽中断信号,哪怕你调用 Thread.interrupt(),它也只默默记下中断状态,等拿到锁之后才抛 InterruptedException——但那时可能已经晚了。而 lockInterruptibly() 从一开始就把中断当作退出条件,只要被中断,立刻放弃排队、清理资源、抛出异常。

典型场景:后台任务执行中用户点了取消、HTTP 请求超时、Spring 的 @Async 方法需支持 cancel、定时任务被 shutdownNow 中断。

注意:lockInterruptibly() 只对「尚未获取到锁」的线程有效;如果线程已持有锁,再中断不会释放它——锁的释放永远只由 unlock() 显式触发。

必须配套 try-catch-finally 的写法

很多人以为加了 lockInterruptibly() 就万事大吉,结果一中断就漏掉 unlock(),造成死锁风险。它不像 synchronized 那样自动释放,必须手动兜底。

立即学习Java免费学习笔记(深入)”;

正确写法只有这一种可靠模式:

Lock lock = new ReentrantLock();
try {
    lock.lockInterruptibly(); // 可能抛 InterruptedException
    // 执行临界区逻辑
} catch (InterruptedException e) {
    // 中断发生:当前线程被外部要求停止,不做重试,直接退出
    Thread.currentThread().interrupt(); // 恢复中断状态(供上层判断)
    return; // 或 throw new RuntimeException(e);
} finally {
    if (lock.isHeldByCurrentThread()) { // 防御性检查,避免 unlock 未持锁线程
        lock.unlock();
    }
}

常见错误:

艺映AI
艺映AI

艺映AI - 免费AI视频创作工具

下载
  • lockInterruptibly() 放在 try 外面 → 中断时根本进不到 finally
  • catch 里没恢复中断状态 → 上层无法感知“这是被中断退出的”
  • 忽略 isHeldByCurrentThread() → 线程没拿到锁就被中断,unlock() 会抛 IllegalMonitorStateException

和 synchronized 对比:中断语义完全不同

synchronized 块完全不响应中断——哪怕你在等待 monitor entry 时被中断,JVM 也不会抛异常,中断标志只会被静默吞掉。所以想靠中断退出 synchronized 等待,根本做不到。

ReentrantLock.lockInterruptibly() 是目前 Java 标准库中唯一能真正实现“可中断等待”的原生机制(Condition.awaitNanos() 同理)。

性能差异可以忽略:两者底层都走 AQS,只是 lockInterruptibly() 多做一次中断检测,开销微乎其微。别为这点性能放弃可中断能力。

兼容性注意:Java 5+ 全支持,但 Android API Level lockInterruptibly()(需降级为轮询 + tryLock(timeout))。

中断后如何让上游知道“任务被取消”

单纯捕获 InterruptedException 并不等于业务层面完成了取消。下游调用方需要明确区分“执行失败”和“主动放弃”。

推荐做法:

  • 方法签名声明 throws InterruptedException,把中断责任向上传递
  • 若封装成 CompletableFuture,用 completeExceptionally(new CancellationException()) 替代 cancel(true),避免丢失中断上下文
  • 在 Spring 中,配合 TaskExecutor 使用时,确保线程池配置了 setThreadFactory 并保留中断传播链

最容易被忽略的一点:中断不是“立即终止线程”,而是发一个信号;线程是否响应、何时响应、响应后做什么,全由你自己代码控制。别指望调了 interrupt() 就万事大吉——锁释放了,但正在写的文件、发的 HTTP 请求、改的数据库,都得你手动收尾。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

154

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

88

2026.01.26

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

764

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

99

2025.12.01

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

384

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2110

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

357

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

259

2023.09.05

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

24

2026.03.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.2万人学习

C# 教程
C# 教程

共94课时 | 11万人学习

Java 教程
Java 教程

共578课时 | 79.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号