ReentrantLock 的 lockInterruptibly() 方法支持可中断加锁,线程在等待锁时被中断会抛出 InterruptedException 并退出;而 lock() 不可中断,易导致资源浪费或死锁。

ReentrantLock 支持可中断的加锁,关键在于调用 lockInterruptibly() 方法,而不是 lock()。当线程在等待获取锁的过程中被其他线程调用 interrupt() 中断时,它会抛出 InterruptedException 并立即退出等待,从而实现响应中断的加锁行为。
为什么需要可中断锁
默认的 lock() 是不可中断的:如果一个线程在等待锁时被中断,它仍会继续阻塞,直到获得锁或发生异常。这可能导致资源浪费、死锁难以排查,或无法及时响应业务取消请求(如超时任务、用户主动取消操作)。lockInterruptibly() 让线程能“听懂”中断信号,提升系统可控性和健壮性。
基本使用方式
使用 lockInterruptibly() 时需注意:必须放在 try-catch 中捕获 InterruptedException,且通常应在 finally 块中释放锁(即使被中断也要确保解锁)。
- 声明一个
ReentrantLock实例(通常为final成员变量) - 在业务逻辑开始前调用
lockInterruptibly() - 在
finally块中调用unlock() - 捕获并处理
InterruptedException(例如记录日志、清理资源、向上抛出或恢复中断状态)
典型代码示例
注意:中断状态不会自动清除,若选择忽略中断,建议手动恢复(Thread.currentThread().interrupt())
立即学习“Java免费学习笔记(深入)”;
private final ReentrantLock lock = new ReentrantLock();
public void doSomething() throws InterruptedException {
lock.lockInterruptibly(); // 可中断地获取锁
try {
// 执行临界区操作
System.out.println("执行业务逻辑");
} finally {
lock.unlock(); // 必须确保释放锁
}
}
调用方可以这样触发中断:
Thread t = new Thread(() -> {
try {
sharedResource.doSomething();
} catch (InterruptedException e) {
System.out.println("被中断,放弃执行");
// 可选择重新设置中断状态
Thread.currentThread().interrupt();
}
});
t.start();
Thread.sleep(100);
t.interrupt(); // 主动中断等待中的线程
与 synchronized 的区别
synchronized 是不可中断的——一旦进入等待队列,就只能等锁释放或 JVM 终止;而 ReentrantLock.lockInterruptibly() 提供了显式的中断支持,是实现协作式取消的重要基础。但要注意:中断仅对“等待锁”的线程生效;如果线程已持有锁并在临界区内执行耗时操作,则需在业务逻辑中主动检查 Thread.interrupted() 来响应中断。


















