AtomicIntegerArray用于多线程下对整型数组单个元素进行原子操作,基于volatile语义和CAS指令实现无锁并发,支持get、set、incrementAndGet、compareAndSet等线程安全方法,但数组长度固定且不支持整体原子操作。

AtomicIntegerArray 是 Java 并发包(java.util.concurrent.atomic)中专为**多线程下安全操作整型数组**设计的类。它内部不直接暴露原始数组,而是通过volatile 语义 + CAS(Compare-And-Swap)指令保证对单个索引位置的读、写、更新操作具有原子性,避免使用 synchronized 或锁带来的开销。
为什么不能直接用普通 int[] 配合 synchronized?
普通数组本身不可被加锁(synchronized 块只能锁对象或 this),若用外部锁保护整个数组,会严重降低并发度——即使两个线程修改不同索引,也会互相阻塞。而 AtomicIntegerArray 支持按索引粒度的无锁原子操作,真正实现“谁改谁的格子,互不干扰”。
核心原子操作方法及使用示例
假设你有一个长度为 10 的共享计数器数组,多个线程需独立递增各自负责的索引位:
初始化:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
立即学习“Java免费学习笔记(深入)”;
AtomicIntegerArray counter = new AtomicIntegerArray(10); // 全部初始为 0
常用原子方法(全部线程安全):
- get(int i):获取索引 i 处当前值(相当于 volatile 读)
- set(int i, int newValue):设置索引 i 处为新值(相当于 volatile 写)
- incrementAndGet(int i):对索引 i 处值原子加 1,并返回新值(最常用)
- getAndIncrement(int i):原子加 1,返回旧值
- compareAndSet(int i, int expect, int update):CAS 操作——仅当当前值等于 expect 时,才设为 update,返回是否成功(适合实现自定义原子逻辑,如条件更新)
- addAndGet(int i, int delta):原子加 delta 并返回新值(比循环 increment 更灵活)
典型并发场景代码片段:
// 线程 A:给索引 3 加 1 counter.incrementAndGet(3); // 线程 B:给索引 7 加 5 counter.addAndGet(7, 5); // 线程 C:仅当索引 0 当前是 10 时,才设为 20 boolean success = counter.compareAndSet(0, 10, 20);
重要注意事项
-
数组长度固定:构造后不可扩容或缩容;如需动态结构,考虑
ConcurrentHashMap<Integer, AtomicInteger>,但会丢失数组的连续内存和索引定位优势 - 不提供整体原子操作:无法原子地“将整个数组清零”或“批量加一”,所有操作都是单索引粒度的。若需批量一致性,仍需额外同步机制
- get/set 是 volatile 语义,不是 synchronized:它们不构成临界区,也不阻止重排序(但满足 happens-before),适合做状态标志或简单计数;复杂逻辑仍需谨慎设计
- 避免误用 get() 后手动计算再 set():这会破坏原子性。必须用 incrementAndGet、addAndGet 或 compareAndSet 等组合操作替代
和 volatile int[] 的区别
Java 不允许声明 volatile int[] 数组(语法错误),即使包装成 volatile int[] ref,也只能保证“引用”的可见性,数组元素仍是普通读写。而 AtomicIntegerArray 保证每个元素的读写都具备 volatile 语义 + CAS 能力,这才是真正意义上的“原子整型数组”。

















