reentrantlock.lockinterruptibly()是可中断加锁方法,线程等待锁时能响应interrupt并抛出interruptedexception;与不可中断的lock()不同,它在中断时立即退出、不持锁,且成功后清除中断状态。

在 Java 中,ReentrantLock.lockInterruptibly() 是一种可响应线程中断的加锁方式,它让线程在等待锁的过程中能被 Thread.interrupt() 打断,从而抛出 InterruptedException 并退出等待,避免无限阻塞。
lockInterruptibly 与 lock 的核心区别
lock() 是不可中断的:即使线程被中断,它仍会继续阻塞,直到获取到锁;而 lockInterruptibly() 是可中断的:一旦线程在等待锁时收到中断信号,立即抛出异常并放弃抢锁,不会进入锁的等待队列或继续等待。
- 调用
lockInterruptibly()前,若当前线程已处于中断状态(Thread.interrupted()返回 true),会直接抛出InterruptedException - 调用过程中被其他线程中断,也会立即抛出异常,且不会持有锁
- 成功获取锁后,该线程的中断状态会被清除(即
Thread.interrupted()返回 false)
正确使用 lockInterruptibly 的典型结构
必须将 lockInterruptibly() 放在 try 块中,并在 catch(InterruptedException) 中做清理和退出处理;锁的释放必须放在 finally 块中,确保无论是否中断都能释放。
ReentrantLock lock = new ReentrantLock();
try {
lock.lockInterruptibly(); // 可能抛出 InterruptedException
// 临界区操作
} catch (InterruptedException e) {
// 处理中断:如记录日志、恢复中断状态、退出任务等
Thread.currentThread().interrupt(); // 推荐:重置中断标志,便于上层感知
return; // 或 throw new RuntimeException(e);
} finally {
if (lock.isHeldByCurrentThread()) { // 防止未加锁就释放
lock.unlock();
}
}
常见应用场景
适合需要“带超时/可取消”的并发任务,比如:
- 线程池中执行耗时任务,外部调用
future.cancel(true)时需及时响应中断 - 交互式服务(如 Web 请求)设置请求超时,超时后中断正在等待资源的线程
- 协作式关闭逻辑:主控线程调用
worker.interrupt(),工作线程在锁等待处退出
注意事项与易错点
容易忽略的关键细节:
- 不要在
catch中吞掉InterruptedException而不恢复中断状态,否则上层无法感知中断意图 -
lockInterruptibly()不是“尝试加锁”,而是“阻塞式但可中断”,它不返回布尔值,失败只通过异常体现 - 如果锁已被当前线程持有,再次调用
lockInterruptibly()会立即成功(重入),不会中断也不会抛异常 - 中断仅对“等待锁”的线程生效;若线程已持有锁并在临界区内执行,中断不会打断执行,只能等到下次调用可中断方法(如
wait()、sleep()或再次lockInterruptibly())才响应
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











