应使用 lockinterruptibly() 当需在等待锁时响应中断(如取消、超时、优雅关闭);它在等待中收到 interrupt() 即抛 interruptedexception 并退出,而 lock() 不响应,会持续阻塞直至获锁。

Java 中使用 ReentrantLock 的 lockInterruptibly() 方法,可以让线程在等待锁的过程中响应中断信号,避免无限期阻塞。这是比 lock() 更灵活、更可控的加锁方式,特别适用于需要及时响应取消、超时或外部干预的场景。
什么时候该用 lockInterruptibly()?
当业务逻辑要求线程在等待锁时能被主动中断(比如用户点击“取消”、服务优雅关闭、任务超时等),就不能用普通 lock() —— 因为它不响应中断,会一直阻塞直到拿到锁。而 lockInterruptibly() 在等待期间一旦收到 Thread.interrupt(),就会抛出 InterruptedException 并立即退出等待,把控制权交还给调用方。
基本用法:try-catch + finally 释放锁
必须配合 try-finally 使用,确保锁在任何路径下都能被释放。注意:lockInterruptibly() 本身可能抛异常,所以加锁操作要放在 try 块外或单独处理。
- 先调用
lockInterruptibly(),若锁可用则立即获取;否则进入等待,并响应中断 - 一旦抛出
InterruptedException,说明线程被中断,应清理资源、退出或重试 - 无论是否成功加锁,只要加锁成功了,就必须在 finally 中 unlock()
典型代码结构
下面是一个安全、标准的写法:
ReentrantLock lock = new ReentrantLock();
try {
// 尝试可中断地获取锁
lock.lockInterruptibly();
// ✅ 持有锁,执行临界区逻辑
doSomethingCritical();
} catch (InterruptedException e) {
// ⚠️ 被中断:可能是主动 cancel,也可能是系统调度中断
Thread.currentThread().interrupt(); // 恢复中断状态(推荐)
// 执行中断处理:如日志、回滚、通知上层
handleInterrupted();
} finally {
if (lock.isHeldByCurrentThread()) { // 防止未加锁就 unlock
lock.unlock();
}
}
和 lock() 的关键区别
lockInterruptibly() 是可中断的等待;lock() 是不可中断的等待。
-
lock():即使线程已被interrupt(),仍会继续阻塞,直到获得锁后才把中断状态设为 true -
lockInterruptibly():只要还在等待锁,一收到中断就立刻抛异常,不会等到获取锁之后 - 两者在已持有锁的情况下调用,都不会抛中断异常——中断只影响“等待中”的状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











