lockInterruptibly 是 ReentrantLock 提供的可中断加锁方式,使线程在等待锁时能响应中断并抛出 InterruptedException;适用于需支持取消、优雅关闭或防死锁的场景,使用时须捕获异常并手动恢复中断状态。

lockInterruptibly 是 ReentrantLock 提供的可中断加锁方式,它让线程在等待锁的过程中能响应中断信号(即收到 Thread.interrupt() 后不再傻等,而是抛出 InterruptedException 并退出阻塞),从而实现更灵活、可控的并发控制。
什么时候必须用 lockInterruptibly 而不是 lock
当你希望线程在等待锁时也能被外部主动取消或超时中止,比如:
- 任务提交后用户点了“取消”,需要快速释放资源并停止等待
- 参与协作的线程需统一响应 shutdown 信号
- 避免死锁场景下无限等待(配合 tryLock + 中断做兜底)
基本用法:捕获 InterruptedException 并正确处理
调用 lockInterruptibly() 必须放在 try 块中,并显式处理 InterruptedException。注意:一旦抛出该异常,锁一定没拿到,无需 unlock。
ReentrantLock lock = new ReentrantLock();
try {
lock.lockInterruptibly(); // 可能抛 InterruptedException
// 执行临界区逻辑
doSomething();
} catch (InterruptedException e) {
// 当前线程被中断:清理资源、退出、或重新设置中断状态
Thread.currentThread().interrupt(); // 推荐:保留中断标记供上层判断
return; // 或 throw new RuntimeException(e);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
中断正在等待锁的线程,会发生什么
假设线程 A 已持有锁,线程 B 调用 lockInterruptibly() 进入阻塞等待:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 此时若其他线程调用
B.interrupt(),B 不会立即获得锁,而是立刻退出阻塞,抛出InterruptedException - B 的中断状态会被清除(这是
lockInterruptibly的行为约定),所以通常需要手动恢复:Thread.currentThread().interrupt() - A 持有的锁不受影响,仍需正常 unlock
和 tryLock + interrupt 配合使用的典型模式
如果想实现“最多等 1 秒,期间允许被中断”,可以组合使用:
if (!lock.tryLock(1, TimeUnit.SECONDS)) {
// 等待超时,但未必被中断;检查是否已被中断
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
// 处理超时逻辑
}
// 成功获取锁后,记得在 finally 中 unlock
不过更简洁的方式仍是直接用 lockInterruptibly(),再配合上层超时调度(如 ExecutorService.invokeAny 或自定义定时器中断)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










