atomicintegerarray仅保障单元素操作的原子性,不支持数组整体或跨索引复合操作的原子性。它通过unsafe cas实现指定索引位置的原子读写,适用于多线程分段计数等场景,但无法替代synchronized或lock对数组整体加锁。

AtomicIntegerArray 能让普通 int 数组的单个元素操作具备原子性,但它不保证整个数组操作的原子性,也不能替代 synchronized 或 Lock 对数组整体加锁。
为什么不能直接用普通数组做并发计数
普通 int[] 在多线程下对同一索引执行 ++ 操作(如 arr[i]++)实际是“读-改-写”三步,非原子。即使只改一个元素,多个线程同时操作同一位置也会丢失更新。AtomicIntegerArray 把每个元素封装成独立的原子整数,通过 Unsafe CAS 指令保障单元素读写安全。
基本用法:初始化与常用操作
创建时传入长度或已有数组(注意:它会复制值,不共享原数组);所有操作都带索引参数,只影响指定位置。
-
初始化:
AtomicIntegerArray arr = new AtomicIntegerArray(10);或new AtomicIntegerArray(new int[]{1,2,3}); -
原子更新:
arr.incrementAndGet(2)(+1 并返回新值),arr.compareAndSet(0, 5, 10)(仅当当前为 5 时设为 10) -
安全读取:
arr.get(3)(比 volatile 读更明确语义),arr.lazySet(1, 99)(延迟写,适合写后不再立即读的场景)
典型适用场景
适合“多线程各自操作不同索引”的模式,比如分段计数、状态标记、缓存命中统计等。
- 线程按 hash 分桶更新计数器:
int idx = threadId % arr.length(); arr.incrementAndGet(idx); - 用作轻量级状态数组(如标记某资源是否就绪),各线程只读写自己负责的 slot
- 避免为每个计数器单独 new AtomicInteger,节省对象头开销
常见误区与限制
它不是万能的“原子数组”,关键点要清楚:
- 不支持原子性地替换整个数组或批量修改多个元素
- 没有
length()以外的元信息方法(如无法原子判断是否全为零) - 如果逻辑需要跨索引的复合操作(例如“若索引 0 大于索引 1 则递增索引 2”),仍需额外同步机制
- 数组长度固定,不可扩容;想动态结构请考虑 ConcurrentMap 或其他并发集合
不复杂但容易忽略:AtomicIntegerArray 解决的是“单元素操作的线程安全”,不是“数组结构的线程安全”。用对场景,它轻量高效;用错地方,反而掩盖并发问题。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











