Java中用lockInterruptibly()实现可中断锁获取,因其在等待时响应中断并抛出InterruptedException,而lock()不可中断;需配合try-catch-finally,且仅在持锁时unlock,并结合isHeldByCurrentThread()安全释放。

Java 中通过 ReentrantLock 实现可中断的锁获取,核心在于使用 lockInterruptibly() 方法替代 lock()。该方法在等待获取锁的过程中响应线程中断,抛出 InterruptedException,从而让线程能及时退出阻塞状态,避免死锁或资源浪费。
为什么用 lockInterruptibly() 而不是 lock()
lock() 是不可中断的:一旦线程进入等待队列,即使被调用 interrupt(),它仍会继续阻塞,直到获得锁或被唤醒(如因超时或被 signal)。而 lockInterruptibly() 在等待期间持续检查中断状态,一旦检测到中断,立即抛出异常并退出等待,使线程有机会清理资源、退出循环或转为其他逻辑。
基本用法:try-lock-interruptible 模式
必须将 lockInterruptibly() 放在 try 块中,并配合 finally 确保解锁。注意:只有在成功获取锁后才需要 unlock;若未获取锁就抛出 InterruptedException,则无需 unlock。
- 先声明锁:
private final ReentrantLock lock = new ReentrantLock(); - 在业务逻辑中使用:
try {
lock.lockInterruptibly(); // 可中断地获取锁
// 执行临界区操作
doSomethingCritical();
} catch (InterruptedException e) {
// 当前线程被中断,放弃获取锁
Thread.currentThread().interrupt(); // 恢复中断状态(推荐)
// 处理中断:如日志、清理、返回或抛出
return;
} finally {
if (lock.isHeldByCurrentThread()) { // 防止未加锁就解锁
lock.unlock();
}
}
结合条件等待时的中断处理
当与 Condition 配合使用(如生产者-消费者),await() 本身也是可中断的。若在 await() 期间被中断,同样抛出 InterruptedException,需在 catch 块中处理并确保锁被正确释放。
立即学习“Java免费学习笔记(深入)”;
-
condition.await()会自动释放锁,并在唤醒时重新竞争锁;但若被中断,不会自动重入锁 - 中断后应显式判断是否持有锁,再决定是否 unlock
- 建议统一在 finally 块中用
isHeldByCurrentThread()安全解锁
实际场景示例:带超时与中断的任务执行
比如一个后台任务需限时执行且支持外部取消:
- 主线程调用
taskThread.interrupt()请求停止 - 任务线程在
lockInterruptibly()或condition.await()中立即响应 - 无需依赖轮询
Thread.interrupted(),减少 CPU 开销和延迟
这种设计比基于 synchronized 的方案更灵活——因为 synchronized 不支持中断等待,只能靠事后检查中断状态,无法真正“提前退出”阻塞。


















