synchronized子句中条件表达式的线程安全性咨询
关于
synchronized(condition ? lockobject : new Object())的线程安全性分析 好问题,这个细节很容易踩坑,咱们一步步拆解清楚:
首先要明确一个关键规则:synchronized括号中的表达式是在进入同步块之前就完成求值的,这部分代码并不受后续同步块的锁保护。
也就是说,当你写synchronized(condition ? lockobject : new Object())时,执行顺序是:
- 先执行
condition ? lockobject : new Object()这个三元表达式,得到一个锁对象 - 尝试获取这个锁对象的监视器锁
- 获取成功后,进入同步块执行代码
所以回到你的疑问:条件表达式的执行过程并没有线程安全性保证——多个线程完全可以同时执行这个三元表达式,哪怕它们之后要进入同步块。举个典型的风险场景:
- 如果
condition是多线程共享的非volatile变量,不同线程可能看到condition的不一致值 - 当条件为false时,多个线程可能同时执行
new Object(),各自创建不同的锁对象,这样后续的同步块相当于没有锁(因为每个线程持有的是不同的锁),完全起不到同步作用
你提到“将条件单独放在一行时并不安全”,其实放在synchronized括号里的情况和单独放一行的风险完全一致——因为这部分代码的执行根本还没进入同步保护的范围。
正确的处理方式
如果需要确保条件判断和锁对象选择的线程安全性,你可以:
- 用一个全局固定的锁对象来保护条件判断和锁对象的选择逻辑,比如:
Object globalLock = new Object(); Object targetLock; synchronized(globalLock) { targetLock = condition ? lockobject : new Object(); } synchronized(targetLock) { // 你的同步代码逻辑 } - 或者确保
condition的读写本身是线程安全的(比如用volatile修饰,或在其他锁保护下修改),但即使这样,也无法避免多个线程同时进入三元表达式的else分支创建多个锁对象的问题——所以更稳妥的方式还是先在一个安全的锁下完成锁对象的选择。
内容的提问来源于stack exchange,提问作者user3740179
相关产品推荐
相关产品推荐

