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

synchronized 不响应中断,但异常时自动释放锁——这是它最核心的行为特征。理解这点,就能避开很多线程卡死、任务无法取消的坑。
等待锁时完全不响应中断
当线程尝试进入 synchronized 块却抢不到锁,会进入 BLOCKED 状态。此时调用 interrupt():
- 只把线程的中断标志设为 true,不会唤醒或退出阻塞
- 线程继续原地等待,直到锁被释放
- 不会抛出 InterruptedException,也没有任何反馈
这意味着:你无法靠 interrupt() 取消一个“正在等锁”的操作。比如服务超时想中断请求,线程却卡在 synchronized 外面动不了。
一旦拿到锁,异常也保证释放
只要线程成功进入 synchronized 代码块(即已持有锁),后续无论发生什么:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 正常执行完,锁自动释放
- 抛出 RuntimeException、Error 或任何未捕获异常,JVM 仍会执行 monitorexit 指令释放锁
- 不需要 try-finally,也不依赖手动清理
底层由字节码保障,安全可靠。例如:
synchronized (lock) { doWork(); }
即使 doWork() 抛 NullPointerException,锁照样释放,不会导致死锁。
需要中断等待?必须换 Lock
如果业务要求“等锁时能被中断”,synchronized 无解,只能改用 ReentrantLock:
- 用 lockInterruptibly() 替代 lock():等待中收到 interrupt 就抛 InterruptedException
- 捕获异常后建议调用 Thread.currentThread().interrupt() 恢复中断状态
- 必须在 finally 中显式 unlock(),且推荐先 check isHeldByCurrentThread()
典型写法:
try { lock.lockInterruptibly(); /* 临界区 */ } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(e); } finally { if (lock.isHeldByCurrentThread()) lock.unlock(); }什么时候该警惕这个限制
以下场景中,synchronized 的不可中断性容易引发问题:
- 远程调用超时机制依赖中断,但线程卡在锁等待上无法退出
- 定时任务被用户取消,线程却因等锁迟迟不终止
- 连接池/资源池分配时,无超时的锁等待造成线程堆积
遇到这些,别硬扛 synchronized,换成可中断、可超时的 Lock 更稳妥。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










