synchronized嵌套的关键是锁对象唯一且加锁顺序统一,避免不同锁交叉导致死锁;应使用final锁对象、缩小同步范围,并优先用ReentrantLock的tryLock超时机制替代。

直接说重点:用 synchronized(变量) 做代码块嵌套,核心不是“能不能嵌”,而是“锁对象是否一致、顺序是否统一”。嵌套本身不危险,危险的是在不同锁对象之间无序切换——这会快速引发死锁。
明确锁对象的唯一性
变量作为锁,必须是同一个实例对象。比如:
- 用
private final Object lock1 = new Object();定义的锁,多个线程都用它,才真正互斥 - 如果每次 new 一个新对象当锁(如
synchronized(new Object())),等于没锁——每个线程拿的都是自己的锁 - 共享变量如果是可变引用(比如被重新赋值过),锁就失效了;建议声明为
final
嵌套时只用同一把锁,避免交叉
不要出现这种写法:
synchronized(lockA) { ... synchronized(lockB) { ... } }synchronized(lockB) { ... synchronized(lockA) { ... } }
两个线程分别按不同顺序进入,立刻形成环路等待。正确做法是:所有涉及 lockA 和 lockB 的操作,强制约定顺序——比如“永远先 lockA,再 lockB”。
缩小同步范围,嵌套只为逻辑分层
嵌套不是为了“套着锁”,而是为了在大逻辑里精准控制小临界区。例如:
- 外层锁 account(保护账户余额)
- 内层只对 logList 加锁(仅保护日志追加,不阻塞余额计算)
- 关键:logList 的锁对象要独立且 final,不能和 account 锁混用
这样既隔离了资源,又避免长时持锁。
替代方案:优先考虑 tryLock + 超时
真需要多锁协作时,synchronized 很难优雅处理。更稳妥的做法是换用 ReentrantLock:
- 用
lock.tryLock(3, TimeUnit.SECONDS)主动设超时 - 失败就释放已持锁、回退重试或报错,不卡死
- 配合
lock.lockInterruptibly()支持中断响应
这比靠人工盯住嵌套顺序更可靠。

















