synchronized通过monitor的重入计数器实现嵌套锁释放:同一线程重复获取同一锁时仅递增\_recursioncount,每次monitorexit递减,归零才清空\_owner并释放锁;该机制保障同步方法嵌套、同步块嵌套及递归调用均正常执行,且异常时仍能正确回退计数。

synchronized 处理嵌套锁释放,靠的是 JVM Monitor 内置的重入计数器,不是“每次进就加一把新锁”,而是同一把锁反复计数——进一次加 1,出一次减 1,归零才真释放。
可重入机制是核心
每个对象监视器(Monitor)里维护两个关键字段:_Owner(当前持有锁的线程)和 _RecursionCount(重入次数)。同一线程再次进入同一把锁时:
- 不检查锁是否被占用,只判断 _Owner 是否为自己
- 是自己就直接递增 _RecursionCount,跳过阻塞与竞争逻辑
- 每次退出同步块或方法(执行 monitorexit),计数器减 1
- 只有计数器减到 0,_Owner 才被清空,锁才对其他线程开放
典型嵌套场景都依赖这个机制
以下写法能正常运行,正是因为计数器在起作用:
-
同步方法调用另一个同步方法:如
methodA()是synchronized,内部调用synchronized methodB(),不会卡住,只是计数 +1 -
同步代码块嵌套同步代码块:用同一个锁对象(比如
this或lockObj)多次加锁,计数器连续累加 -
递归调用自身:
synchronized void recur() { recur(); }每进一层计数 +1,直到栈溢出或退出条件满足
异常或提前退出不影响计数逻辑
哪怕嵌套很深,中间某层抛出 RuntimeException 或 Error,JVM 仍会按字节码顺序逐层执行 monitorexit 指令:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 每执行一次,计数器就减 1
- 即使某层没走完,只要进了同步区域,就一定有对应的退出指令保障计数回落
- 不需要 try-finally,也不怕忘记释放——这是 synchronized 自动管理的优势
和不可重入锁对比更清楚
如果 synchronized 不可重入,下面代码会死锁:
synchronized(this) {
System.out.println("第一层");
synchronized(this) {
System.out.println("第二层"); // 实际能执行到
}
}
但实际能输出两行。第二层不是重新抢锁,而是线程发现自己已持锁,仅把计数从 1 变成 2;退出时计数依次回到 1、再回到 0,锁才释放。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










