synchronized高并发吞吐量下降主因是锁升级引发阻塞与上下文切换;优化需减少竞争、缩小临界区、合理分锁、善用jvm锁优化,并区分读写场景:写用synchronized+volatile,读多时可无锁+vola。

synchronized 在高并发下吞吐量下降,核心不是它“天生慢”,而是锁升级到重量级后引发线程阻塞、上下文切换和内核态开销;优化关键在于减少竞争、缩短临界区、用对锁粒度,并善用 JVM 自带的锁优化机制。
只锁真正需要同步的部分,避免同步方法和大块代码
把非共享逻辑(如日志、IO、计算、参数校验)移出 synchronized 块,只包裹读写共享变量的核心操作。例如:
- ❌ 错误写法:整个业务方法加 synchronized,包含远程调用和 JSON 序列化
- ✅ 正确写法:先完成耗时操作,再用最小同步块更新状态字段
同步代码块比同步方法更可控,能精准锁定对象实例或专用锁对象,而非整个 this 或 Class。
按业务维度拆分锁对象,避免单点热点
多个线程反复修改同一个对象(比如全局计数器、用户会话缓存),会让该对象成为“热点”,所有线程排队等一把锁。解决方式是分散锁竞争:
- 按用户 ID、订单号哈希取模,分桶加锁(如 lockMap.get(userId % 16))
- 为不同数据类型或业务域使用独立锁对象(如 userLock、orderLock、cacheLock)
- 参考 LongAdder 的分段累加思想:用数组 + CAS 分片,写操作不争同一把锁
读多写少场景:读不加锁 + volatile 保可见性
读操作本身不改状态,只要保证可见性即可并行执行。synchronized 的释放-获取语义天然提供可见性,但仅限于“经过锁”的读写路径。可组合使用:
- 写方法用 synchronized(保障原子性 + 刷新主内存)
- 被读字段声明为 volatile(保障无锁读的实时性,适用于基本类型或引用)
- 注意:若读取涉及多个字段需强一致性(如 balance 和 status 要同时有效),仍需整体加锁
信任 JVM 的锁优化机制,但别依赖它兜底
JVM 在运行期会动态优化锁行为,包括:
- 偏向锁:单线程反复进入时几乎零开销(适合初始化、ThreadLocal 初始化等)
- 轻量级锁 + 自适应自旋:短临界区竞争时避免挂起线程,节省上下文切换
- 锁消除:JIT 发现对象未逃逸(如局部 StringBuilder),直接删掉 synchronized
- 锁粗化:合并循环内连续加锁,减少锁操作频次
这些优化无需编码干预,但要求代码结构合理——比如避免在循环内创建新对象、减少锁作用域,才能让逃逸分析和粗化生效。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











