atomicintegerarray基于cas实现数组元素的原子更新,通过unsafe计算内存偏移量并调用compareandswapint完成cpu级原子操作,volatile int[]无法保证元素级原子性。

CAS(Compare-And-Swap)是 Java 并发包中实现无锁原子操作的核心机制,AtomicIntegerArray 正是基于 CAS 对数组元素做线程安全的更新,它不加锁、不阻塞,适合高并发读多写少的场景。
AtomicIntegerArray 底层怎么用 CAS 更新单个元素
它内部维护一个普通 int[] 数组,并通过 Unsafe 类的 CAS 方法(如 compareAndSwapInt)直接操作内存地址。每次更新前,先读取当前值,再比较是否仍为预期值,只有相等才替换——整个过程由 CPU 指令保证原子性。
例如调用 array.compareAndSet(2, 10, 20):
- 先计算索引 2 对应的内存偏移量(基于数组首地址 + 偏移)
- 调用 Unsafe.compareAndSwapInt(array, offset, 10, 20)
- 若位置 2 当前值确实是 10,则设为 20 并返回 true;否则返回 false,不修改
为什么不能直接用 volatile int[] 实现原子更新
volatile 只能保证单个变量的可见性和禁止重排序,但对数组来说:
-
volatile int[] arr仅保证数组引用的可见性,数组元素本身不具 volatile 语义 -
arr[i]++是“读-改-写”三步操作,即使元素是 volatile,也无法避免竞态条件 - CAS 将这三步封装成一条不可分割的 CPU 指令,真正实现原子性
常用原子操作方法与使用要点
AtomicIntegerArray 提供了多种基于 CAS 的方法,它们都以索引为单位操作,彼此独立:
-
getAndSet(int i, int newValue):获取旧值并设置新值(CAS 循环直到成功) -
incrementAndGet(int i):原子自增,等价于getAndAdd(i, 1) -
accumulateAndGet(int i, int x, IntBinaryOperator op):支持自定义运算(如 max、min),底层仍是 CAS 自旋 -
weakCompareAndSetPlain等弱版本适用于对失败容忍度高的场景,性能略高但不保证 happens-before
注意:所有方法只保障单个索引位置的操作原子性,多个索引间的组合操作(如“把索引 0 和 1 同时加 1”)仍需额外同步控制。
实际使用中的典型模式
常见于计数器分片、状态位管理、轻量级聚合统计等场景:
- 分段计数:用
AtomicIntegerArray模拟多个独立计数器,避免锁争用 - 状态标记:每个索引代表一个任务 ID,用
compareAndSet标记“处理中→完成”,防止重复执行 - 避免扩容:它包装的是固定大小数组,初始化后长度不可变,适合已知规模的场景
不复杂但容易忽略:数组一旦创建,其底层 int[] 就不可替换;若需动态伸缩,应考虑 ConcurrentHashMap 或配合其他结构设计。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











