atomicinteger自增比synchronized快因底层用cas无锁,避免线程挂起/唤醒开销;但高竞争时可能更慢。需正确使用getandincrement()(先返后加)和incrementandget()(先加后返),禁用循环compareandset模拟自增。

AtomicInteger自增为什么比synchronized快
因为底层用的是CAS(Compare-And-Swap),不加锁,避免了线程挂起/唤醒开销。但前提是竞争不激烈——如果多个线程反复抢同一个值失败重试,反而可能比轻量级锁慢。
常见错误现象:getAndIncrement() 返回旧值,有人误以为它返回新值,结果逻辑错位;还有人用 incrementAndGet() 却没接返回值,白白浪费原子性。
-
incrementAndGet():先加再返回,适合“加完立刻要用新值”的场景(如生成唯一ID) -
getAndIncrement():先返回再加,适合“记数但不依赖本次结果”的场景(如统计请求次数) - 别在循环里无脑调用
compareAndSet(old, old + 1)—— 这是incrementAndGet()的手动低效实现,还容易漏处理ABA问题(不过对整数自增影响极小)
什么时候不能用AtomicInteger替代synchronized
AtomicInteger只保证单个变量的原子读写,不保证多步操作的原子性。比如“先判断是否小于100,再加1”,这俩动作合起来不是原子的,if (counter.get() 依然会超限。
使用场景:计数器、序列号、状态标志位等单一整型操作;不适合库存扣减、余额变更这类需校验+更新组合逻辑的业务。
- 需要条件更新?用
compareAndSet(expected, updated),但得自己循环重试 - 涉及多个变量联动?必须上锁,或改用
StampedLock/ReadWriteLock - 数值范围超出
int?直接换AtomicLong,别强转,AtomicInteger不支持 long
并发下get()和incrementAndGet()的可见性问题
不会有问题。AtomicInteger 所有方法都具有 volatile 语义,写操作对其他线程立即可见,不需要额外加 volatile 或同步块。
容易踩的坑:有人把 AtomicInteger 当普通 int 传参,比如 process(counter.get()),然后在 process 里缓存这个值做后续判断——此时缓存的是快照,不代表最新状态。
- 别缓存
get()结果用于跨方法逻辑判断,除非你明确知道中间无并发修改 - 日志打点时用
get()没问题,但监控告警阈值检查建议用incrementAndGet()后立刻判断,避免两次读之间的窗口 - 调试时别只看
toString()输出,它调的是get(),不是实时快照——高并发下连续打印可能看到“倒退”数字(其实是不同时间点的读取)
与LongAdder对比:高并发下该选谁
当写远多于读、且不要求严格实时一致性时,LongAdder 更快;但如果你需要精确值(比如作为分布式ID种子)、或频繁读取最新值做决策,还是用 AtomicInteger。
性能差异本质:AtomicInteger 是单点竞争,LongAdder 把计数分散到多个 cell,降低冲突,但 sum() 要遍历所有 cell,开销略大。
- QPS 上万、纯累加统计(如埋点)?优先
LongAdder - 需要
compareAndSet或getAndSet?只能用AtomicInteger,LongAdder不提供这些方法 - 初始化后几乎只读?
AtomicInteger和普通int差距不大,没必要上原子类









