介绍一下java.util.concurrent.atomic基础包

37 阅读7分钟

java.util.concurrent.atomic(简称 Atomic 包)是 Java 并发编程的核心基础包,JDK 1.5 引入,专为 多线程环境下的原子操作 设计。它基于 CAS(Compare-And-Swap)原子指令 + volatile 可见性 实现无锁并发,避免了 synchronized 等锁机制的线程阻塞 / 上下文切换开销,兼顾线程安全与高性能。

核心目标:解决多线程对单个变量的  “读取 - 修改 - 写入” 复合操作原子性问题(如 i++count += n),同时提供可见性和有序性保证(依赖 volatile 和 CAS 语义)。

一、核心设计思想

Atomic 包的所有类遵循统一设计原则,底层依赖 sun.misc.Unsafe 类(封装 CPU 原子指令)实现核心能力:

  1. 无锁设计:不依赖锁(synchronized/Lock),通过 CAS 自旋重试解决并发冲突,轻量级且高效(低冲突场景性能远超锁)。

  2. volatile 可见性:所有原子类的核心变量(如 AtomicInteger 的 value)均被 volatile 修饰,确保修改后立即写回主内存,其他线程实时读取最新值。

  3. CAS 原子性:依赖 CPU 提供的 cmpxchg 原子指令,实现 “比较 - 替换” 的原子操作,核心逻辑:

    • 读取当前内存值 V
    • 比较 V 与预期值 E 是否一致;
    • 若一致,将 V 更新为新值 N,返回成功;若不一致,重试(自旋)直到成功。
  4. API 简洁性:提供直观的原子操作方法(如 incrementAndGet()compareAndSet()),无需手动处理锁逻辑。

二、包结构与核心类分类

Atomic 包的类按功能可分为 5 大类,覆盖 基本类型、引用类型、数组、字段更新、复合操作 等场景,核心类如下:

类别核心类功能描述
基本类型原子类AtomicIntegerAtomicLongAtomicBooleanAtomicByte原子操作 int/long/boolean/byte 等基本类型
引用类型原子类AtomicReferenceAtomicStampedReferenceAtomicMarkableReference原子更新对象引用,解决 ABA 问题
数组类型原子类AtomicIntegerArrayAtomicLongArrayAtomicReferenceArray原子更新数组元素(避免数组元素并发冲突)
字段更新器原子类AtomicIntegerFieldUpdaterAtomicLongFieldUpdaterAtomicReferenceFieldUpdater反射机制原子更新对象的字段(无需修改原类)
复合操作原子类(JDK8+)LongAdderDoubleAdderLongAccumulatorDoubleAccumulator高并发场景优化,支持自定义复合操作(如最大值统计)

三、各类核心类详解(含使用场景)

1. 基本类型原子类(最常用)

针对基本类型的原子增减、赋值、比较替换,解决简单数值的并发安全问题。

  • 核心类AtomicIntegerint)、AtomicLonglong)、AtomicBooleanboolean)。

  • 核心 APIincrementAndGet()(自增)、addAndGet(delta)(累加)、compareAndSet(expect, update)(比较替换)。

  • 适用场景:计数器(接口调用量、QPS)、序号生成器(订单 ID)、简单状态标记(如 “已处理数量”)。

  • 示例

    java

    运行

    AtomicInteger counter = new AtomicInteger(0);
    counter.incrementAndGet(); // 原子自增(++i)
    counter.addAndGet(5); // 原子累加 5
    boolean success = counter.compareAndSet(6, 10); // 若当前值为6,更新为10
    

2. 引用类型原子类

针对 对象引用 的原子操作,避免多线程修改引用导致的对象不一致,解决 CAS 中的 ABA 问题。

  • 核心类

    • AtomicReference:普通引用原子更新(如原子替换配置对象);
    • AtomicStampedReference:带版本号的引用(解决 ABA 问题,如链表操作);
    • AtomicMarkableReference:带布尔标记的引用(简化版 ABA 解决方案,仅判断是否修改)。
  • 适用场景:原子更新配置对象、单例对象、缓存更新、链表节点操作。

  • 示例AtomicStampedReference 解决 ABA):

    java

    运行

    // 初始值"A",版本戳0
    AtomicStampedReference<String> stampedRef = new AtomicStampedReference<>("A", 0);
    // 比较并替换:预期值"A"、版本0 → 更新为"C"、版本1(版本不匹配则失败)
    boolean success = stampedRef.compareAndSet("A", "C", 0, 1);
    

3. 数组类型原子类

原子更新数组元素,避免多线程修改数组时的并发冲突(如分桶计数场景)。

  • 核心类AtomicIntegerArrayint[])、AtomicLongArraylong[])、AtomicReferenceArray(引用数组)。

  • 核心 APIgetAndIncrement(index)(指定索引原子自增)、compareAndSet(index, expect, update)(指定索引比较替换)。

  • 适用场景:分桶计数(如按用户 ID 分桶统计访问量)、原子更新缓存数组。

  • 示例

    java

    运行

    AtomicIntegerArray bucketCounts = new AtomicIntegerArray(10); // 10个分桶
    int bucketIndex = Math.abs("user123".hashCode()) % 10;
    bucketCounts.incrementAndGet(bucketIndex); // 对应分桶原子自增
    

4. 字段更新器原子类

通过 反射机制 原子更新对象的实例字段或静态字段,无需修改原类源码(如第三方库类)。

  • 核心类AtomicIntegerFieldUpdaterint 字段)、AtomicLongFieldUpdaterlong 字段)、AtomicReferenceFieldUpdater(引用字段)。

  • 关键限制:目标字段必须是 volatile(保证可见性)、非 final(可修改)、非 private(反射可访问)。

  • 适用场景:修改第三方库类的字段、无需侵入原类的原子更新。

  • 示例

    java

    运行

    // 第三方类(字段为 volatile int)
    class ThirdParty { volatile int count; }
    
    // 创建字段更新器
    AtomicIntegerFieldUpdater<ThirdParty> updater = 
        AtomicIntegerFieldUpdater.newUpdater(ThirdParty.class, "count");
    
    ThirdParty obj = new ThirdParty();
    updater.incrementAndGet(obj); // 原子自增 count 字段
    

5. 复合操作原子类(JDK8+ 新增)

针对高并发场景优化,内部分桶存储减少 CAS 冲突,支持自定义复合操作(如最大值、最小值统计),性能远超传统原子类。

  • 核心类

    • LongAdder/DoubleAdder:高并发累加(AtomicLong/AtomicDouble 的高性能替代);
    • LongAccumulator/DoubleAccumulator:支持自定义复合操作(如最大值、自定义聚合逻辑)。
  • 适用场景:高并发 QPS 统计、流量统计、复杂聚合计算(如实时最大值)。

  • 示例LongAdder 高并发计数):

    java

    运行

    LongAdder qpsAdder = new LongAdder();
    qpsAdder.increment(); // 原子自增(分桶存储,冲突少)
    System.out.println("QPS:" + qpsAdder.sum()); // 合并分桶结果
    

四、Atomic 包的核心特性与限制

1. 核心优势

  • 高性能:无锁设计,避免线程阻塞和上下文切换,低冲突场景下性能是 synchronized 的数倍。
  • 线程安全:通过 CAS 原子指令和 volatile 保证原子性、可见性、有序性。
  • API 简洁:无需手动处理锁逻辑,直接调用原子操作方法(如 incrementAndGet()),开发效率高。
  • 兼容性:底层依赖 JVM 封装的 CPU 原子指令,适配不同操作系统(Windows、Linux)和 CPU 架构(x86、ARM)。

2. 关键限制

  • 仅支持单变量原子性:单个 API 是原子的,但多个原子操作组合(如 “先自增再判断阈值”)不原子,需手动用 compareAndSet() 循环包裹。
  • ABA 问题:传统原子类(如 AtomicIntegerAtomicReference)存在 ABA 漏洞,需用 AtomicStampedReference 或 AtomicMarkableReference 解决。
  • 高冲突场景性能下降:若上千线程同时 CAS 操作同一变量,自旋重试会消耗大量 CPU,此时需改用 LongAdder(分桶)或锁机制。
  • 不支持批量操作:原子类仅针对单个变量 / 数组元素,批量更新多个变量需额外同步。

五、Atomic 包的典型应用场景

  1. 高并发计数器:接口调用量、QPS、用户在线数、订单量统计(AtomicInteger/AtomicLong/LongAdder)。
  2. 序号生成器:订单 ID、用户 ID、请求序列号生成(AtomicLong)。
  3. 原子更新配置:多线程环境下替换整个配置对象(AtomicReference)。
  4. 分桶统计:按哈希分桶减少并发冲突(AtomicIntegerArray/AtomicLongArray)。
  5. 第三方类字段更新:无需修改源码,原子更新第三方库的字段(AtomicIntegerFieldUpdater)。
  6. 高并发聚合计算:实时统计最大值、最小值、自定义聚合逻辑(LongAccumulator)。

六、使用建议与选型指南

场景需求推荐类替代方案
简单 int/long 计数AtomicInteger/AtomicLong高并发用 LongAdder
布尔状态标记AtomicBooleanAtomicReference<Boolean>
原子更新对象引用AtomicReference需避免 ABA 用 AtomicStampedReference
数组元素原子操作AtomicIntegerArray/AtomicLongArray手动加锁(性能差)
第三方类字段原子更新AtomicIntegerFieldUpdater 等无(唯一非侵入式方案)
高并发亿级计数LongAdderAtomicLong(低并发可用)
复杂聚合计算(最大值 / 自定义)LongAccumulator锁 + 普通变量(代码繁琐)

核心原则

  • 低并发、简单场景:优先用 AtomicInteger/AtomicLong(API 简洁,学习成本低);
  • 高并发计数:用 LongAdder(分桶无锁,性能最优);
  • 引用更新 / ABA 问题:用 AtomicReference/AtomicStampedReference
  • 第三方类 / 数组场景:用字段更新器 / 数组原子类;
  • 复合逻辑 / 多变量操作:用 synchronized 或 Lock(保证整体原子性)。

七、总结

java.util.concurrent.atomic 是 Java 并发编程的 基础工具包,核心价值是 “无锁实现单变量原子操作”,平衡了线程安全与高性能。它屏蔽了底层 CPU 原子指令和 volatile 语义的复杂性,提供了简洁易用的 API,是计数器、序号生成器、原子配置更新等场景的首选方案。

理解 Atomic 包的核心原理(CAS + volatile)和各类的适用场景,能帮助开发者在多线程编程中避免并发问题,同时提升程序性能。它也是很多高级并发工具(如 ConcurrentHashMapThreadPoolExecutor)的底层依赖。