Atomic包核心在于“用对场景”:6种原子类各解决特定并发问题,混淆使用易引入bug;需依场景选型,避免误当通用同步工具。

Atomic 包的核心不是“会用”,而是“用对场景”。6 种原子类(AtomicInteger、AtomicLong、AtomicBoolean、AtomicReference、AtomicStampedReference、AtomicMarkableReference)各自解决一类并发问题,混淆使用反而引入 bug。
基础数值型:别当普通变量用
AtomicInteger 和 AtomicLong 适合计数器、序列号生成等简单累加/递减场景。它们的 incrementAndGet()、compareAndSet(expected, updated) 是线程安全的核心,但要注意:
– 不支持复合运算(如 i += 2),必须拆成 get + compute + compareAndSet 循环重试;
– 高频更新下,CAS 失败重试可能引发“自旋开销”,此时应考虑 LongAdder(JDK8+)替代;
– 初始值设为 0 并不总是合理,比如分布式 ID 生成器需从特定偏移开始。
AtomicBoolean:真不是 boolean 的线程安全版
它本质是封装了 int 值(0/1)的 CAS 操作,适用于状态开关(如“是否已初始化”、“是否已关闭”)。关键点:
– getAndSet(true) 可实现“抢占式置位并获知原状态”,比先 get 再 set 更可靠;
– 不要把它当成可多次切换的 flag 来做复杂状态机——缺乏内存语义保障,多状态建议用 AtomicReference + 枚举;
– lazySet(false) 可避免写屏障开销,适合只关心最终一致性的关闭信号。
AtomicReference:引用安全的起点,不是万能容器
它保证引用本身的读写原子性,但不保证对象内部字段线程安全。典型用法:
– 实现无锁栈、队列(如 Treiber Stack);
– 封装不可变对象(如配置快照)供多线程读取;
– 配合 Unsafe 或 VarHandle 实现更细粒度控制(需谨慎);
– 注意:若引用的对象可变(如 AtomicReference),add() 等操作仍需外部同步。
带版本/标记的引用:专治 ABA 问题
AtomicStampedReference 和 AtomicMarkableReference 解决的是“值相同但中间被改过”的 ABA 问题,但它们不是通用解法:
– AtomicStampedReference 用整数戳记(stamp),适合需要区分“第几次修改”的场景(如乐观锁重试计数);
– AtomicMarkableReference 用布尔标记,常用于标记“逻辑删除”(如链表节点标记为已删,后续清理);
– stamp 和 mark 本身不自动增长,需业务代码维护;
– 过度依赖戳记可能掩盖设计缺陷——真正该重构的是共享状态的粒度或生命周期管理。
AtomicInteger 存用户余额,看似线程安全,却漏掉了扣款前的余额校验和事务一致性。










