代码改变世界

AtomicArray详解

2025-06-28 16:20  halberts  阅读(26)  评论(0)    收藏  举报

1.AtomicArray 详解

AtomicArray 是 Java 提供的一种线程安全工具类,用于处理多个元素的原子操作。常见实现包括:

AtomicIntegerArray:支持 int 类型数组的原子操作。
AtomicLongArray:支持 long 类型数组的原子操作。
AtomicReferenceArray:支持引用类型数组的原子操作。
这些类的设计基于无锁(lock-free)机制,通过底层的 CAS(Compare-And-Swap)操作,提供线程安全的操作而不需要显式加锁。

2. 主要特点

线程安全:每个元素的读写操作都是线程安全的,确保并发环境下数据的正确性。
高性能:基于 CAS 实现的原子操作,无需显式锁定,避免线程阻塞和上下文切换的开销。
无锁操作:避免了锁的使用,尤其在高并发环境下表现出色。
可操作多个元素:提供数组形式,支持对每个数组元素进行独立的原子性操作。

 

3. 主要实现类

1. AtomicIntegerArray

概述:用于对 int 类型数组的每个元素执行原子操作。
构造方法:
AtomicIntegerArray(int length):创建指定长度的数组,元素初始值为 0。
AtomicIntegerArray(int[] array):使用现有数组初始化,原数组会被拷贝。
常用方法:
get(int index):获取指定索引的值。
set(int index, int value):设置指定索引的值。
getAndSet(int index, int value):获取旧值并设置新值。
compareAndSet(int index, int expect, int update):CAS 操作。
getAndIncrement(int index):获取值并自增。
incrementAndGet(int index):自增并获取值。

import java.util.concurrent.atomic.AtomicIntegerArray;

public class AtomicIntegerArrayExample {
    public static void main(String[] args) {
        AtomicIntegerArray atomicArray = new AtomicIntegerArray(5);

        // 初始化值
        atomicArray.set(0, 10);

        // 自增操作
        int oldValue = atomicArray.getAndIncrement(0);
        System.out.println("Old Value: " + oldValue); // 输出: 10
        System.out.println("New Value: " + atomicArray.get(0)); // 输出: 11

        // CAS 操作
        boolean updated = atomicArray.compareAndSet(0, 11, 20);
        System.out.println("Update Successful: " + updated); // 输出: true
        System.out.println("Updated Value: " + atomicArray.get(0)); // 输出: 20
    }
}

 

2. AtomicLongArray

概述:用于对 long 类型数组的每个元素执行原子操作。
构造方法:
AtomicLongArray(int length):创建指定长度的数组,元素初始值为 0。
AtomicLongArray(long[] array):使用现有数组初始化,原数组会被拷贝。
常用方法:
与 AtomicIntegerArray 类似,方法针对 long 类型。

import java.util.concurrent.atomic.AtomicLongArray;

public class AtomicLongArrayExample {
    public static void main(String[] args) {
        AtomicLongArray atomicArray = new AtomicLongArray(new long[] {10L, 20L, 30L});

        // 自减操作
        long oldValue = atomicArray.getAndDecrement(1);
        System.out.println("Old Value: " + oldValue); // 输出: 20
        System.out.println("New Value: " + atomicArray.get(1)); // 输出: 19

        // CAS 操作
        boolean updated = atomicArray.compareAndSet(1, 19, 25);
        System.out.println("Update Successful: " + updated); // 输出: true
        System.out.println("Updated Value: " + atomicArray.get(1)); // 输出: 25
    }
}

3. AtomicReferenceArray

概述:支持对引用类型数组的原子操作。
构造方法:
AtomicReferenceArray(int length):创建指定长度的数组,元素初始值为 null。
AtomicReferenceArray(E[] array):使用现有数组初始化,原数组会被拷贝。
常用方法:
get(int index):获取指定索引的引用。
set(int index, E value):设置指定索引的引用。
compareAndSet(int index, E expect, E update):CAS 操作。
getAndSet(int index, E newValue):获取旧值并设置新值。

import java.util.concurrent.atomic.AtomicReferenceArray;

public class AtomicReferenceArrayExample {
    public static void main(String[] args) {
        AtomicReferenceArray<String> atomicArray = new AtomicReferenceArray<>(3);

        // 设置值
        atomicArray.set(0, "A");
        atomicArray.set(1, "B");

        // CAS 操作
        boolean updated = atomicArray.compareAndSet(1, "B", "C");
        System.out.println("Update Successful: " + updated); // 输出: true
        System.out.println("Updated Value: " + atomicArray.get(1)); // 输出: C
    }
}

4. AtomicArray 的性能表现

优点:
基于 CAS 的原子操作,性能高于显式加锁。
避免了锁竞争问题,尤其适用于读多写少的场景。
缺点:
在高冲突情况下,CAS 操作可能多次重试,导致忙等待。
不能解决复杂场景下的并发问题,例如多个元素间的原子性操作。
适用场景:
多线程环境下,对数组中单个元素进行高频更新的场景。
对数组中的数据需要保证线程安全,但不需要操作多个元素之间的原子性。
注意事项
数据初始化:构造方法会拷贝原始数组,原数组的修改不会影响 AtomicArray。
ABA 问题:和其他基于 CAS 的工具类似,AtomicArray 也存在 ABA 问题。如果需要解决,使用带版本号的方案。
大数组性能:在处理大数组时,AtomicArray 的每次操作需要访问主存,相较于本地缓存数组性能稍逊。

5.总结

AtomicArray 提供了线程安全的数组操作,适合在并发环境中对单个数组元素执行原子操作。
实现方式基于 CAS,性能较高,但适合高并发读写少量冲突的场景。
常见实现包括 AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray,分别支持整型、长整型和引用类型数据。
在实际开发中,AtomicArray 常用于计数器、状态记录器等需要线程安全的数组数据场景。