Java 24+中synchronized块不主动让出平台线程,长期持锁会阻塞其他虚拟线程;应仅在同步块内执行轻量操作,将I/O、复杂逻辑移出,优先使用AtomicInteger或ReentrantLock配合超时机制。

避免 synchronized 长时间持有锁
虚拟线程(Java 24+)环境下,synchronized 块不会主动让出平台线程,哪怕内部执行的是耗时 I/O 或计算。一个虚拟线程长期持锁,会阻塞其他等待该锁的虚拟线程,导致并发吞吐骤降。
- 只在同步块内做轻量操作:如简单计数、状态标记更新
- 把 I/O、网络调用、复杂逻辑移出 synchronized 块
- 高并发计数优先用 AtomicInteger,而非 synchronized 方法
- 复杂同步场景改用 ReentrantLock,便于配合超时、中断或非阻塞设计
防止死锁:统一锁顺序 + 避免嵌套
多个线程以不同顺序获取多个锁,极易形成循环等待。例如线程 A 先锁账户1再锁账户2,线程 B 反过来操作,就可能卡死。
- 所有代码路径对同一组资源按固定顺序加锁(如按对象 ID 升序)
- 尽量不写多层 synchronized 嵌套;若必须,确保嵌套深度和顺序全局一致
- 考虑用 tryLock() 设置超时,失败后释放已获锁并重试或回退
解决可见性与竞态条件
非原子操作(如 count++)或未同步的变量读写,在多线程下可能丢失更新或读到过期值。
- 共享可变状态的简单操作,优先使用 volatile(适用于单次读/写,如开关标志)
- 复合操作(读-改-写)必须加锁或用原子类(如 AtomicInteger.incrementAndGet())
- 避免在无同步保障下依赖“先检查后执行”逻辑(如 if (list.isEmpty()) list.add(x))
别忽略锁升级与偏向锁前提
JVM 的锁升级机制(偏向锁 → 轻量级锁 → 重量级锁)不是万能的。偏向锁仅在单线程反复进入同一同步块时生效;一旦有第二个线程竞争,就会触发撤销,带来额外开销。
立即学习“Java免费学习笔记(深入)”;
- 高并发短临界区场景,JVM 可能跳过偏向锁,直接走轻量级锁
- 若明确存在多线程争用,可通过 JVM 参数 -XX:-UseBiasedLocking 关闭偏向锁,减少撤销成本
- 不要假设 synchronized 总是“很轻”,要结合实际压测判断其开销是否可接受


















