原子变量能安全自增因封装了读-改-写原子操作,而普通int的i++分三步且非原子,volatile仅保可见性不保原子性;Java用AtomicInteger的incrementAndGet等方法,C++用std::atomic的fetch_add等,但多变量同步或复杂逻辑仍需锁。

直接用 AtomicInteger(Java)或 std::atomic(C++)就能安全自增,不用锁、不丢数、不重复。
为什么普通 int 自增会出错
看似简单的 i++,实际分三步:读内存值 → 加 1 → 写回内存。多线程下,两个线程可能同时读到 100,各自加 1 后都写回 101,结果只加了一次。volatile 只能保可见性,不能保原子性,同样解决不了。
Java 中用 AtomicInteger 的正确姿势
核心是用封装好的原子方法,避免手写复合逻辑:
-
incrementAndGet():先加 1,再返回新值(类似++i) -
getAndIncrement():先返回当前值,再加 1(类似i++) - 初始化建议显式传参,如
new AtomicInteger(0),别依赖默认值 - 仅对单个变量的简单操作(++、--、set、compareAndSet)是原子的;若需“读值→判断→更新”,得用
updateAndGet或加锁
C++ 中用 std::atomic 的关键点
C++ 原子类型更通用,支持多种内存序,日常计数用宽松序足够:
- 声明:
std::atomiccounter{0}; - 自增:
counter.fetch_add(1, std::memory_order_relaxed); - 读值:
counter.load();,写值:counter.store(100); - 避免直接用
++counter(虽等价于 fetch_add,但语义不如显式调用清晰) - 不适用于结构体或数组整体操作,需配合
atomic_ref或数组专用类(如atomic_int_array)
什么情况不能只靠原子变量
原子变量不是万能锁,适用边界要清楚:
- 多个变量需同步更新(如账户余额 + 日志状态),必须用互斥锁
- 含条件分支的复合逻辑(如“余额 > 100 才扣款”),
compareAndSet可尝试,但易写错,推荐synchronized或ReentrantLock - 高竞争场景(上千线程争一个计数器),CAS 可能反复失败,此时锁的开销未必更高,需实测权衡










