atomicinteger性能优于synchronized,尤其在高并发下:前者基于cas无锁自旋,避免上下文切换;后者依赖monitor锁机制,高竞争时线程挂起/唤醒开销大,100+线程下吞吐量可降3倍以上。

在计数这类简单共享变量更新场景中,synchronized 和 AtomicInteger 的开销差异主要体现在锁机制、CPU调度与竞争响应方式上。选错方案可能让吞吐量下降3倍以上,尤其在100+线程并发时。
锁 vs 无锁:底层开销来源完全不同
synchronized 是基于 JVM 监视器(Monitor)的重量级同步机制:
- 每次进入临界区需获取对象锁,涉及锁标识位检查、可能的锁膨胀(偏向→轻量→重量)
- 高竞争下线程被挂起/唤醒,触发操作系统上下文切换,单次切换开销常达 1–10 微秒
- 即使无竞争,偏向锁也有少量 JVM 元数据维护成本
AtomicInteger 依赖 CPU 级 CAS 指令(如 x86 的 cmpxchg):
- 无锁、无上下文切换,失败时仅自旋重试(忙等待)
- 单次 CAS 是硬件原子操作,耗时通常
- 开销集中在“冲突重试”——多线程反复读-算-写失败时,CPU 资源被空转消耗
线程数对实际开销的影响很关键
不是“AtomicInteger 总是更快”,而是性能拐点取决于并发密度:
- 10 线程以内:两者差距小(
- 50–200 线程:AtomicInteger 吞吐量可达 synchronized 的 3–5 倍(JMH 实测)
- 500+ 线程且写操作密集:AtomicInteger 自旋加剧,CPU 使用率飙升,而 synchronized 可能因线程阻塞反而更稳
此时建议切换到 LongAdder——它用分段累加+最终合并,把竞争分散到多个 Cell 上,高并发写场景下比 AtomicInteger 更平滑。
代码粒度决定 synchronized 是否划算
如果计数只是方法中的一小步,而整个方法还需保护其他逻辑(比如“先查库存再扣减再发消息”),那 synchronized 的开销就被摊薄了:
- 加一次锁,保护一整段业务逻辑,合理
- 只为
count++单独加锁,属于过度同步,开销占比畸高 - AtomicInteger 在这种纯计数场景下,代码更轻、语义更精准、扩展性更好
别忽略 volatile 的误导性“低开销”
有人试图用 volatile int count 替代两者,这是危险的:
- volatile 仅保证可见性与有序性,不保证
count++的原子性(读-改-写三步非原子) - 实测 10 线程下结果丢失率常达 5–15%,且随线程数增加急剧恶化
- 表面看无锁无同步,实际因数据错误导致重试、补偿或业务异常,隐性开销远超 Atomic 或 sync
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











