synchronized不响应中断但异常时自动释放锁:等待锁时调用interrupt()仅设标志位,线程仍阻塞且不抛interruptedexception;而进入同步块后无论正常退出或抛异常,jvm均保证锁释放。

synchronized 不响应中断,但持有锁的线程在异常退出时仍会自动释放锁。这是它和显式锁(如 ReentrantLock)最核心的区别之一:等待锁的过程不可打断,而锁的释放机制却很可靠。
synchronized 等待过程不响应中断
当多个线程竞争同一个 synchronized 锁时,未抢到锁的线程会进入 BLOCKED 状态。此时调用该线程的 interrupt() 方法:
- 中断标志会被设为 true,但线程不会退出 BLOCKED 状态
- 线程继续原地等待,直到锁被持有者释放
- 不会抛出
InterruptedException,也不会提前返回
这意味着你无法通过中断来“取消”一个正在等 synchronized 锁的操作——它不具备可取消性。
持有锁的线程即使抛异常也会释放锁
只要线程进入了 synchronized 代码块(即已成功获取锁),无论后续是正常执行完毕,还是因未捕获异常(包括 RuntimeException 或 Error)而退出,JVM 都会保证锁被释放:
- 底层通过
monitorenter和monitorexit字节码指令配对实现 -
monitorexit在方法出口或异常表中被插入,由 JVM 自动保障执行 - 不需要手动处理,也不依赖
finally块
例如,以下代码中即使 doWork() 抛出 NullPointerException,锁依然会被释放:
doWork(); // 可能抛异常
return result;
}
想支持中断?得换用 Lock 接口
如果业务需要“等待锁时可被中断”,必须放弃 synchronized,改用 java.util.concurrent.locks.Lock 的实现,比如 ReentrantLock:
- 调用
lockInterruptibly():等待期间收到中断会立即抛出InterruptedException,并放弃等待 - 调用
tryLock(long, TimeUnit):支持超时,避免无限等待 - 需显式
unlock(),推荐放在finally块中
这是权衡:synchronized 简单安全但僵化;Lock 更灵活但需谨慎管理。
小结:什么时候该担心中断问题
实际开发中,以下场景要特别注意 synchronized 的不可中断性:
- 高延迟服务调用中,线程长时间阻塞在锁上,无法响应服务熔断或超时中断
- 任务调度器中,用户主动取消任务,但线程卡在 synchronized 块外等待锁,无法及时退出
- 资源池(如连接池)分配时,若获取锁失败且无超时机制,可能引发线程堆积
遇到这类需求,就别硬扛 synchronized,换成可中断、可超时的锁更稳妥。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











