AtomicLongArray 是 Java 并发包中支持索引级无锁 CAS 操作的线程安全 long 数组,每个元素独立原子更新,需手动重试失败操作,适用于多独立计数场景;构造后长度固定,越界抛异常;高竞争单点累加宜用 LongAdder 或 AtomicLong。

AtomicLongArray 是 Java 并发包(java.util.concurrent.atomic)中提供的线程安全数组类,它支持对数组中**指定索引位置的 long 元素**进行无锁的 CAS(Compare-And-Swap)操作,无需显式加锁,底层依赖 CPU 的原子指令(如 cmpxchg)实现。
直接使用 compareAndSet 方法完成无锁更新
这是最常用、最直观的方式。每个元素独立维护自己的原子状态,compareAndSet(int index, long expect, long update) 会原子性地检查索引 index 处当前值是否等于 expect,若是则设为 update,返回 true;否则返回 false。
- 操作只影响单个索引,不影响其他元素
- 调用者需自行处理失败重试逻辑(如在循环中反复尝试)
- 适合实现计数器、标志位、状态标记等场景
配合 get 和 set 实现更复杂的原子逻辑
虽然 get(index) 和 set(index, value) 本身不是 CAS,但它们是 volatile 语义的读写,可与 compareAndSet 组合使用。例如实现“获取并自增”:
- 先
get(index)读当前值 - 计算新值(如 +1)
- 用
compareAndSet(index, oldVal, newVal)尝试更新 - 失败则重读再试,直到成功(即典型的 CAS 循环惯用法)
注意索引越界和数组不可变性
AtomicLongArray 构造后长度固定,且不提供扩容能力:
立即学习“Java免费学习笔记(深入)”;
- 构造时传入 int 数组或指定长度,内部复制一份 long[],后续无法改变大小
- 所有方法(包括
compareAndSet)都会校验索引范围,越界抛IndexOutOfBoundsException - 不要试图通过反射修改底层数组,会破坏原子性保证
替代方案:何时考虑 LongAdder 或普通 AtomicLong
如果只是频繁对**单个固定位置**做累加,AtomicLongArray 没问题;但若热点集中在少数索引(比如总用 index=0),CAS 可能因高竞争而反复失败:
- 高并发累加场景下,
LongAdder更高效(分段计数+最终合并) - 若只需一个原子 long 变量,直接用
AtomicLong更简洁 -
AtomicLongArray的优势在于:多个逻辑上独立的 long 值需要各自原子更新,且索引动态可变(如按用户 ID 映射到数组槽位)


















