
在Java并发编程中,AtomicInteger 和 synchronized 都可用于实现线程安全,但它们的性能特性和适用场景有显著差异。以下是详细对比:
特性 | AtomicInteger | synchronized |
|---|---|---|
实现原理 | 基于CAS(Compare-and-Swap)指令 | 基于JVM的监视器锁(Monitor) |
硬件支持 | 依赖CPU的原子指令(如x86的 | 依赖JVM的锁升级机制(偏向锁→轻量级锁→重量级锁) |
线程状态 | 无阻塞,通过自旋重试实现原子性 | 可能导致线程阻塞(重量级锁状态) |
性能差异主要取决于 竞争程度 和 操作复杂度:
synchronized。以下是不同竞争程度下的吞吐量对比(操作次数/秒,越高越好):
线程数 | AtomicInteger | synchronized | 场景 |
|---|---|---|---|
1 | 15,000,000 | 10,000,000 | 单线程无竞争 |
4 | 8,000,000 | 5,000,000 | 低竞争 |
16 | 3,000,000 | 7,000,000 | 高竞争 |
测试环境:Intel i7 CPU,JDK 11,HotSpot VM
场景 | 推荐方案 | 原因 |
|---|---|---|
简单原子操作(如计数器) |
| 轻量级,无线程阻塞,低竞争下性能最优。 |
复杂同步逻辑(如复合操作) |
| 可保护多行代码,避免原子操作的局限性。 |
高竞争环境下的复合操作 |
| 可通过 |
读写分离场景 |
| 允许多个读线程并发访问,写线程独占。 |
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCounter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // 原子自增
}
public int get() {
return count.get(); // 原子获取
}
}public class SyncCounter {
private int count = 0;
public synchronized void increment() {
count++; // 同步块保证原子性
}
public synchronized int get() {
return count;
}
}AtomicInteger 是首选。synchronized,尽量缩小同步块范围。LongAdder 在高并发下性能优于 AtomicLong,适合统计类场景。选择时需根据实际场景权衡 性能 和 代码复杂度,必要时通过JMH基准测试验证方案。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。