ReentrantLock 本身不支持可撤销,但可通过 lockInterruptibly() 响应中断、配合 volatile 取消标志和定期检查实现任务取消:lockInterruptibly() 避免锁等待无限阻塞,捕获 InterruptedException 后恢复中断并退出;执行中需在循环条件及耗时操作前后检查 cancelled 标志。

Java 中 ReentrantLock 本身不直接支持“可撤销”语义,但可以通过组合 Thread.interrupt()、lockInterruptibly() 和任务状态标记(如 volatile boolean)来构建具备取消能力的任务单元。关键在于将锁获取与中断响应、任务执行逻辑解耦,并在关键点检查中断状态或取消标志。
使用 lockInterruptibly() 响应中断
ReentrantLock 提供 lockInterruptibly() 方法,它在等待锁的过程中可被中断,抛出 InterruptedException。这是实现可撤销的第一道防线——避免任务在锁竞争阶段无限阻塞。
- 调用前确保当前线程未被中断(可选:先检查
Thread.interrupted()) - 捕获
InterruptedException后,通常应恢复中断状态(Thread.currentThread().interrupt())并提前退出 - 不要忽略该异常,也不要仅打印日志后继续执行
在任务执行中定期检查取消信号
加锁成功后,任务主体可能耗时较长。需主动轮询取消标志(例如 volatile boolean),尤其在循环、长耗时操作前后插入检查点。
- 定义
private volatile boolean cancelled = false;作为外部可控的取消开关 - 在循环条件中加入
&& !cancelled,例如:while (i - 在 sleep、wait、I/O 等可能阻塞处,优先使用可中断版本(如
Thread.sleep()会响应中断)
配合 Condition 实现条件等待的可中断唤醒
若任务需等待某条件成立(如资源就绪),应使用 Condition.awaitInterruptibly() 而非 await()。这样外部调用 condition.signalAll() 或线程被中断都能使等待线程及时退出。
立即学习“Java免费学习笔记(深入)”;
- 通过
lock.newCondition()创建条件变量 - 用
awaitInterruptibly()替代await(),并在 catch 块中处理中断 - 唤醒逻辑(signal)应在线程安全上下文中执行,避免竞态
封装成可管理的任务对象
将锁、取消标志、执行逻辑封装为一个类,提供 cancel() 和 isCancelled() 方法,便于统一控制生命周期。
-
cancel()设置标志位,并在必要时调用Thread.interrupt()(针对正在阻塞的线程) - 执行逻辑入口方法(如
run())开头检查if (cancelled) return; - finally 块中务必释放锁(
lock.unlock()),推荐用 try-finally 或 try-with-resources(配合自定义 AutoCloseable 封装)


















