JDK 8 AtomicIntegerArray 源码详解(详细注释版)
1. 类定义和基本属性
public class AtomicIntegerArray implements java.io.Serializable {
// 序列化版本号
private static final long serialVersionUID = 2862133569453604235L;
/**
* Unsafe类实例,提供底层的原子操作
* 通过Unsafe可以直接操作内存地址,实现CAS等原子操作
*/
private static final sun.misc.Unsafe unsafe = getUnsafe();
/**
* 数组的第一个元素在内存中的偏移量
* 用于计算数组元素的内存地址
*/
private static final int base = unsafe.arrayBaseOffset(int[].class);
/**
* 数组元素之间的地址增量(步长)
* 用于计算数组中任意元素的内存地址
*/
private static final int shift;
/**
* 静态初始化块,计算shift值
* 根据数组元素的地址增量确定位移量
*/
static {
int scale = unsafe.arrayIndexScale(int[].class);
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
shift = 31 - Integer.numberOfLeadingZeros(scale);
}
/**
* 获取Unsafe实例的方法
* 由于Unsafe类的特殊性,需要通过反射获取实例
* @return Unsafe实例
*/
private static sun.misc.Unsafe getUnsafe() {
try {
return sun.misc.Unsafe.getUnsafe();
} catch (SecurityException se) {
try {
return java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
public sun.misc.Unsafe run() throws Exception {
Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
for (java.lang.reflect.Field f : k.getDeclaredFields()) {
f.setAccessible(true);
Object x = f.get(null);
if (k.isInstance(x))
return k.cast(x);
}
throw new NoSuchFieldError("the Unsafe");
}});
} catch (java.security.PrivilegedActionException e) {
throw new RuntimeException("Could not initialize intrinsics",
e.getCause());
}
}
}
/**
* 实际存储的int数组
* 使用volatile修饰确保内存可见性
* 所有原子操作都是针对这个数组进行的
*/
private final int[] array;
/**
* 构造方法,创建指定长度的AtomicIntegerArray
* @param length 数组长度
*
* 初始化过程:
* 1. 创建指定长度的int数组
* 2. 数组元素初始化为0(int的默认值)
* 3. volatile语义确保对其他线程的可见性
*
* @throws NegativeArraySizeException 如果length为负数
*/
public AtomicIntegerArray(int length) {
array = new int[length];
}
/**
* 构造方法,从给定数组创建AtomicIntegerArray
* @param array 给定的int数组
*
* 初始化过程:
* 1. 复制给定数组的内容
* 2. 创建新的int数组存储副本
* 3. volatile语义确保对其他线程的可见性
*
* @throws NullPointerException 如果array为null
*/
public AtomicIntegerArray(int[] array) {
// 复制数组内容,避免外部修改影响内部状态
this.array = Arrays.copyOf(array, array.length);
}
/**
* 获取数组长度
*
* 时间复杂度:O(1)
* 线程安全性:完全线程安全
*
* @return 数组长度
*/
public final int length() {
return array.length;
}
/**
* 获取指定索引位置的值
* 通过Unsafe直接读取数组元素,保证获取最新的值
*
* 时间复杂度:O(1)
* 线程安全性:完全线程安全
*
* @param i 索引位置
* @return 指定位置的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int get(int i) {
return getRaw(checkedByteOffset(i));
}
/**
* 原子地设置指定索引位置的值并返回旧值
* 这是一个原子操作,保证读取和设置的原子性
*
* 操作过程:
* 1. 读取指定位置的当前值
* 2. 设置新值
* 3. 返回旧值
*
* 时间复杂度:O(1)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param newValue 新值
* @return 旧值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int getAndSet(int i, int newValue) {
return getAndSetRaw(checkedByteOffset(i), newValue);
}
/**
* 原子地比较并设置指定索引位置的值
* 只有当当前值等于期望值时,才设置为新值
*
* 操作过程:
* 1. 比较指定位置的当前值和期望值
* 2. 如果相等,将当前值设置为新值
* 3. 返回比较结果
*
* CAS操作特点:
* - 无锁操作,性能优秀
* - 乐观锁机制,避免阻塞
* - 可能出现ABA问题
*
* 时间复杂度:O(1)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param expect 期望值
* @param update 新值
* @return 如果设置成功返回true,否则返回false
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final boolean compareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
/**
* 弱原子地比较并设置指定索引位置的值
* 与compareAndSet类似,但在某些平台上可能不提供完全的内存排序保证
*
* 使用场景:
* - 对内存排序要求不严格的场景
* - 性能要求极高的场景
*
* @param i 索引位置
* @param expect 期望值
* @param update 新值
* @return 如果设置成功返回true,否则返回false
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final boolean weakCompareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
2. 原子更新方法(详细注释)
/**
* 原子地增加1并返回旧值
* 这是一个原子的自增操作
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 计算新值(当前值+1)
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回旧值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @return 增加前的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int getAndIncrement(int i) {
return getAndAdd(i, 1);
}
/**
* 原子地减少1并返回旧值
* 这是一个原子的自减操作
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 计算新值(当前值-1)
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回旧值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @return 减少前的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int getAndDecrement(int i) {
return getAndAdd(i, -1);
}
/**
* 原子地增加指定值并返回旧值
* 这是一个原子的加法操作
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 计算新值(当前值+delta)
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回旧值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param delta 要增加的值
* @return 增加前的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int getAndAdd(int i, int delta) {
return getAndAddRaw(checkedByteOffset(i), delta);
}
/**
* 原子地增加1并返回新值
* 这是一个原子的自增操作
*
* 与getAndIncrement的区别:
* - getAndIncrement返回旧值
* - incrementAndGet返回新值
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 计算新值(当前值+1)
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回新值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @return 增加后的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int incrementAndGet(int i) {
return addAndGet(i, 1);
}
/**
* 原子地减少1并返回新值
* 这是一个原子的自减操作
*
* 与getAndDecrement的区别:
* - getAndDecrement返回旧值
* - decrementAndGet返回新值
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 计算新值(当前值-1)
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回新值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @return 减少后的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int decrementAndGet(int i) {
return addAndGet(i, -1);
}
/**
* 原子地增加指定值并返回新值
* 这是一个原子的加法操作
*
* 与getAndAdd的区别:
* - getAndAdd返回旧值
* - addAndGet返回新值
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 计算新值(当前值+delta)
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回新值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param delta 要增加的值
* @return 增加后的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int addAndGet(int i, int delta) {
return getAndAddRaw(checkedByteOffset(i), delta) + delta;
}
/**
* 原子地更新值,使用指定的更新函数
* 这是Java 8新增的方法,支持函数式编程
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 使用updateFunction计算新值
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回新值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param updateFunction 更新函数
* @return 更新后的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
long offset = checkedByteOffset(i);
int prev, next;
do {
prev = getRaw(offset);
next = updateFunction.applyAsInt(prev);
} while (!compareAndSetRaw(offset, prev, next));
return next;
}
/**
* 原子地更新值,使用指定的更新函数
* 返回更新前的值
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 使用updateFunction计算新值
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回旧值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param updateFunction 更新函数
* @return 更新前的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
long offset = checkedByteOffset(i);
int prev, next;
do {
prev = getRaw(offset);
next = updateFunction.applyAsInt(prev);
} while (!compareAndSetRaw(offset, prev, next));
return prev;
}
/**
* 原子地累积值,使用指定的累积函数
* 这是Java 8新增的方法,支持累积操作
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 使用accumulatorFunction计算累积值
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回新值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param x 要累积的值
* @param accumulatorFunction 累积函数
* @return 累积后的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int accumulateAndGet(int i, int x,
IntBinaryOperator accumulatorFunction) {
long offset = checkedByteOffset(i);
int prev, next;
do {
prev = getRaw(offset);
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSetRaw(offset, prev, next));
return next;
}
/**
* 原子地累积值,使用指定的累积函数
* 返回累积前的值
*
* 操作过程:
* 1. 获取指定位置的当前值
* 2. 使用accumulatorFunction计算累积值
* 3. 使用CAS操作更新值
* 4. 如果CAS失败,重复步骤1-3
* 5. 返回旧值
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
* 线程安全性:完全原子性
*
* @param i 索引位置
* @param x 要累积的值
* @param accumulatorFunction 累积函数
* @return 累积前的值
* @throws IndexOutOfBoundsException 如果索引越界
*/
public final int getAndAccumulate(int i, int x,
IntBinaryOperator accumulatorFunction) {
long offset = checkedByteOffset(i);
int prev, next;
do {
prev = getRaw(offset);
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSetRaw(offset, prev, next));
return prev;
}
3. 辅助方法(详细注释)
/**
* 检查数组索引并计算字节偏移量
* 确保索引在有效范围内,并计算对应的内存偏移量
*
* @param i 数组索引
* @return 对应的字节偏移量
* @throws IndexOutOfBoundsException 如果索引越界
*/
private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
return byteOffset(i);
}
/**
* 计算数组索引对应的字节偏移量
* 使用base偏移量和shift计算元素的内存地址
*
* @param i 数组索引
* @return 对应的字节偏移量
*/
private static long byteOffset(int i) {
return ((long) i << shift) + base;
}
/**
* 通过Unsafe获取指定偏移量位置的值
*
* @param offset 内存偏移量
* @return 指定位置的值
*/
private int getRaw(long offset) {
return unsafe.getIntVolatile(array, offset);
}
/**
* 通过Unsafe原子地设置指定偏移量位置的值并返回旧值
*
* @param offset 内存偏移量
* @param newValue 新值
* @return 旧值
*/
private int getAndSetRaw(long offset, int newValue) {
return unsafe.getAndSetInt(array, offset, newValue);
}
/**
* 通过Unsafe原子地比较并设置指定偏移量位置的值
*
* @param offset 内存偏移量
* @param expect 期望值
* @param update 新值
* @return 如果设置成功返回true,否则返回false
*/
private boolean compareAndSetRaw(long offset, int expect, int update) {
return unsafe.compareAndSwapInt(array, offset, expect, update);
}
/**
* 通过Unsafe原子地增加指定偏移量位置的值并返回旧值
*
* @param offset 内存偏移量
* @param delta 要增加的值
* @return 旧值
*/
private int getAndAddRaw(long offset, int delta) {
return unsafe.getAndAddInt(array, offset, delta);
}
4. 字符串表示方法(详细注释)
/**
* 返回对象的字符串表示
* 重写Object类的toString方法
*
* @return 数组内容的字符串表示
*/
public String toString() {
int iMax = array.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(get(i));
if (i == iMax)
return b.append(']').toString();
b.append(',').append(' ');
}
}
/**
* 计算对象的哈希码
* 重写Object类的hashCode方法
*
* @return 对象的哈希码
*/
public int hashCode() {
int result = 1;
for (int i = 0; i < array.length; i++) {
int element = get(i);
result = 31 * result + element;
}
return result;
}
/**
* 比较两个AtomicIntegerArray对象是否相等
* 重写Object类的equals方法
*
* @param obj 要比较的对象
* @return 如果相等返回true,否则返回false
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof AtomicIntegerArray))
return false;
AtomicIntegerArray that = (AtomicIntegerArray) obj;
if (array.length != that.array.length)
return false;
for (int i = 0; i < array.length; i++)
if (get(i) != that.get(i))
return false;
return true;
}
5. AtomicIntegerArray 的特点分析
核心设计理念:
/**
* AtomicIntegerArray的核心设计思想:
*
* 1. 数组原子操作:
* - 提供对数组元素的原子操作
* - 每个元素都可以独立进行原子操作
* - 支持细粒度的并发控制
*
* 2. 无锁编程:
* - 使用CAS(Compare-And-Swap)操作实现原子性
* - 避免传统锁的开销和阻塞
* - 提供乐观锁机制
*
* 3. volatile语义:
* - array字段使用final修饰,数组引用不可变
* - 数组元素通过Unsafe的volatile操作保证可见性
* - 确保读操作获取最新值
*
* 4. Unsafe支持:
* - 使用sun.misc.Unsafe类提供底层原子操作
* - 直接操作数组元素的内存地址,性能优异
* - 绕过JVM的常规访问控制
*
* 5. 偏移量机制:
* - 通过数组基地址和元素偏移量直接访问内存
* - 避免反射开销
* - 提供精确的内存操作
*
* 6. 自旋重试:
* - CAS失败时自动重试
* - 保证操作的最终成功
* - 适用于竞争不激烈的场景
*
* 7. 函数式支持:
* - Java 8新增函数式更新方法
* - 支持lambda表达式
* - 提供更灵活的原子操作
*
* 8. 边界检查:
* - 所有操作都进行索引边界检查
* - 防止数组越界异常
* - 提供安全的数组访问
*
* 适用场景:
* - 多线程环境下的计数器数组
* - 状态标志数组
* - 需要原子操作的整数数组
* - 高并发环境下的数组操作
* - 需要细粒度并发控制的场景
*/
性能特征分析:
/**
* AtomicIntegerArray的性能特征:
*
* 时间复杂度:
* - get(i): O(1) - 直接读取数组元素
* - compareAndSet(i, expect, update): O(1) 平均,O(∞) 最坏
* - getAndIncrement(i): O(1) 平均,O(∞) 最坏
* - incrementAndGet(i): O(1) 平均,O(∞) 最坏
* - getAndAdd(i, delta): O(1) 平均,O(∞) 最坏
* - addAndGet(i, delta): O(1) 平均,O(∞) 最坏
*
* 空间复杂度:
* - O(n) - 需要存储n个int值
* - 每个元素都有固定的内存开销
*
* 并发特性:
* - 完全线程安全
* - 每个数组元素可以独立进行原子操作
* - 无锁设计,避免线程阻塞
* - 乐观锁机制,适用于低竞争场景
* - 高竞争场景下可能出现自旋开销
*
* 与synchronized数组对比:
* - 无竞争:AtomicIntegerArray > synchronized数组
* - 低竞争:AtomicIntegerArray > synchronized数组
* - 高竞争:AtomicIntegerArray可能 < synchronized数组
* - 内存开销:AtomicIntegerArray < synchronized数组
*
* 与AtomicInteger[]对比:
* - 功能相似:都提供原子操作
* - 内存使用:AtomicIntegerArray < AtomicInteger[]
* - 性能:AtomicIntegerArray ≥ AtomicInteger[]
* - 管理复杂度:AtomicIntegerArray < AtomicInteger[]
*
* CAS操作特点:
* - 乐观锁:假设没有冲突,冲突时重试
* - 非阻塞:不会阻塞其他线程
* - ABA问题:需要额外机制解决
* - 自旋开销:高竞争时CPU使用率可能较高
*
* 内存使用:
* - 每个实例存储一个数组引用
* - 数组元素通过volatile保证可见性
* - 及时GC,避免内存泄漏
*
* 适用性:
* - 数组元素原子操作:性能优异
* - 高频数组更新场景:性能优异
* - 复杂同步逻辑:可能不如锁机制
* - 需要精确控制:比锁更灵活
*/
6. 使用示例和最佳实践
/**
* 使用示例:
*
* // 基本使用
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 原子设置和获取
* array.set(0, 100);
* int value = array.get(0);
*
* // 原子自增
* int oldValue = array.getAndIncrement(0); // 返回旧值
* int newValue = array.incrementAndGet(0); // 返回新值
*
* // 原子自减
* int oldValue2 = array.getAndDecrement(0);
* int newValue2 = array.decrementAndGet(0);
*
* // 原子加法
* int oldValue3 = array.getAndAdd(0, 5);
* int newValue3 = array.addAndGet(0, 5);
*
* // 比较并设置
* boolean success = array.compareAndSet(0, 10, 20);
* if (success) {
* System.out.println("Value updated successfully");
* } else {
* System.out.println("Value update failed");
* }
*
* // 从现有数组创建
* int[] initialValues = {1, 2, 3, 4, 5};
* AtomicIntegerArray array2 = new AtomicIntegerArray(initialValues);
*
* // 函数式更新(Java 8+)
* int result = array2.updateAndGet(0, x -> x * 2);
* int previous = array2.getAndUpdate(0, x -> x + 1);
*
* // 累积操作(Java 8+)
* int accumulated = array2.accumulateAndGet(0, 10, Integer::sum);
* int previousAcc = array2.getAndAccumulate(0, 5, Math::max);
*
* // 多线程计数器数组示例
* class ThreadSafeCounterArray {
* private final AtomicIntegerArray counters;
*
* public ThreadSafeCounterArray(int size) {
* counters = new AtomicIntegerArray(size);
* }
*
* public void increment(int index) {
* counters.incrementAndGet(index);
* }
*
* public void decrement(int index) {
* counters.decrementAndGet(index);
* }
*
* public void add(int index, int delta) {
* counters.addAndGet(index, delta);
* }
*
* public int get(int index) {
* return counters.get(index);
* }
*
* public int size() {
* return counters.length();
* }
*
* public boolean compareAndSet(int index, int expect, int update) {
* return counters.compareAndSet(index, expect, update);
* }
* }
*
* // 状态标志数组示例
* class StatusFlagArray {
* private final AtomicIntegerArray flags;
*
* public StatusFlagArray(int size) {
* flags = new AtomicIntegerArray(size);
* }
*
* public void setStatus(int index, boolean status) {
* flags.set(index, status ? 1 : 0);
* }
*
* public boolean getStatus(int index) {
* return flags.get(index) != 0;
* }
*
* public boolean trySetStatus(int index, boolean expected, boolean newValue) {
* int expect = expected ? 1 : 0;
* int update = newValue ? 1 : 0;
* return flags.compareAndSet(index, expect, update);
* }
*
* public void resetAll() {
* for (int i = 0; i < flags.length(); i++) {
* flags.set(i, 0);
* }
* }
* }
*
* // 统计信息收集示例
* class StatisticsCollector {
* private final AtomicIntegerArray statistics;
* public static final int REQUEST_COUNT = 0;
* public static final int ERROR_COUNT = 1;
* public static final int SUCCESS_COUNT = 2;
* public static final int TOTAL_COUNT = 3;
*
* public StatisticsCollector() {
* statistics = new AtomicIntegerArray(4);
* }
*
* public void recordRequest() {
* statistics.incrementAndGet(REQUEST_COUNT);
* }
*
* public void recordError() {
* statistics.incrementAndGet(ERROR_COUNT);
* }
*
* public void recordSuccess() {
* statistics.incrementAndGet(SUCCESS_COUNT);
* statistics.incrementAndGet(TOTAL_COUNT);
* }
*
* public int getRequestCount() {
* return statistics.get(REQUEST_COUNT);
* }
*
* public int getErrorCount() {
* return statistics.get(ERROR_COUNT);
* }
*
* public int getSuccessCount() {
* return statistics.get(SUCCESS_COUNT);
* }
*
* public int getTotalCount() {
* return statistics.get(TOTAL_COUNT);
* }
*
* public void reset() {
* for (int i = 0; i < statistics.length(); i++) {
* statistics.set(i, 0);
* }
* }
* }
*
* 最佳实践:
*
* 1. 正确使用原子操作:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 正确的做法:使用原子操作
* array.incrementAndGet(0);
*
* // 错误的做法:非原子操作
* // array.set(0, array.get(0) + 1); // 不是原子操作!
*
* 2. 合理使用compareAndSet:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 正确使用:检查返回值
* public boolean tryUpdate(int index, int expected, int newValue) {
* return array.compareAndSet(index, expected, newValue);
* }
*
* // 错误使用:忽略返回值
* // array.compareAndSet(0, 0, 1); // 没有检查返回值
*
* 3. 选择合适的获取方法:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 当需要旧值时使用getAnd系列方法
* int oldValue = array.getAndIncrement(0);
* System.out.println("Old value was: " + oldValue);
*
* // 当需要新值时使用incrementAndGet等方法
* int newValue = array.incrementAndGet(0);
* System.out.println("New value is: " + newValue);
*
* 4. 处理CAS失败的情况:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 使用循环确保操作成功
* public boolean updateValue(int index, int expected, int newValue) {
* return array.compareAndSet(index, expected, newValue);
* }
*
* // 或者使用函数式方法
* public int doubleValue(int index) {
* return array.updateAndGet(index, x -> x * 2);
* }
*
* 5. 避免ABA问题:
* // ABA问题示例:值从A变为B再变为A
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 线程1准备更新
* int expected = array.get(0); // 获取到10
*
* // 线程2执行:10 -> 20 -> 10
* array.compareAndSet(0, 10, 20);
* array.compareAndSet(0, 20, 10);
*
* // 线程1执行:CAS成功,但实际上中间状态发生了变化
* array.compareAndSet(0, expected, 30); // 成功,但可能不是期望的行为
*
* // 解决方案:使用版本号或时间戳
* class VersionedArray {
* private final AtomicIntegerArray values;
* private final AtomicIntegerArray versions;
*
* public VersionedArray(int size) {
* values = new AtomicIntegerArray(size);
* versions = new AtomicIntegerArray(size);
* }
*
* public boolean compareAndSet(int index, int expectedValue,
* int expectedVersion, int newValue) {
* int currentVersion = versions.get(index);
* if (currentVersion != expectedVersion) {
* return false; // 版本不匹配
* }
* if (!values.compareAndSet(index, expectedValue, newValue)) {
* return false; // 值不匹配
* }
* versions.incrementAndGet(index); // 更新版本
* return true;
* }
* }
*
* 6. 合理使用函数式更新:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 简单操作使用专门方法
* array.incrementAndGet(0); // 比函数式更快
*
* // 复杂操作使用函数式方法
* int result = array.updateAndGet(0, x -> {
* // 复杂计算
* return complexCalculation(x);
* });
*
* 7. 边界检查:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 始终进行边界检查
* public void safeIncrement(int index) {
* if (index >= 0 && index < array.length()) {
* array.incrementAndGet(index);
* } else {
* throw new IndexOutOfBoundsException("Index out of bounds: " + index);
* }
* }
*
* // 或者让AtomicIntegerArray自动处理
* // array.incrementAndGet(10); // 会抛出IndexOutOfBoundsException
*
* 8. 监控和调试:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 定期检查数组状态
* public void logArrayStatus() {
* System.out.println("Array contents: " + array.toString());
* }
*
* // 性能监控
* public void monitorPerformance() {
* long startTime = System.nanoTime();
* // 执行一些操作
* for (int i = 0; i < 1000000; i++) {
* array.incrementAndGet(i % array.length());
* }
* long endTime = System.nanoTime();
* System.out.println("Time taken: " + (endTime - startTime) + " ns");
* }
*
* 9. 批量操作优化:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* // 避免频繁的原子操作
* // 错误做法:每次循环都进行原子操作
* // for (int i = 0; i < 1000; i++) {
* // array.incrementAndGet(0);
* // }
*
* // 正确做法:批量更新(如果可能)
* // 对于数组元素,通常无法批量更新,但可以优化访问模式
* public void optimizedBatchUpdate() {
* // 尽量减少不必要的原子操作
* int currentValue = array.get(0);
* if (currentValue < 1000) {
* array.addAndGet(0, 1000 - currentValue);
* }
* }
*
* 10. 异常处理:
* AtomicIntegerArray array = new AtomicIntegerArray(10);
*
* public void safeUpdate(int index, IntUnaryOperator updateFunction) {
* try {
* array.updateAndGet(index, updateFunction);
* } catch (IndexOutOfBoundsException e) {
* System.err.println("Index out of bounds: " + e.getMessage());
* } catch (Exception e) {
* System.err.println("Update failed: " + e.getMessage());
* // 记录日志或采取其他措施
* }
* }
*
* 11. 性能调优:
* // 在高并发场景下监控性能
* AtomicIntegerArray array = new AtomicIntegerArray(1000);
*
* // 使用局部变量减少数组访问
* public void optimizedAccess(int index) {
* int localValue = array.get(index);
* if (localValue > 0) {
* // 执行相关逻辑
* }
* }
*
* // 避免不必要的原子操作
* public void conditionalOperation(int index) {
* if (array.get(index) > 0) { // 先检查
* // 再执行原子操作
* array.compareAndSet(index, array.get(index), 0);
* }
* }
*/
7. 与其他原子类的比较
/**
* AtomicIntegerArray vs AtomicInteger vs AtomicReferenceArray vs 普通数组:
*
* AtomicIntegerArray:
* - 用于int数组的原子操作
* - 每个元素支持独立的原子操作
* - 提供丰富的数学运算方法
* - 适用于需要原子操作的整数数组
*
* AtomicInteger:
* - 用于单个int值的原子操作
* - 提供与AtomicIntegerArray类似的方法
* - 适用于单个计数器或状态值
*
* AtomicReferenceArray:
* - 用于对象引用数组的原子操作
* - 支持CAS操作对象引用
* - 适用于复杂对象数组的原子操作
* - 可以配合版本控制解决ABA问题
*
* 普通数组:
* - 非线程安全的数组操作
* - 需要外部同步机制
* - 性能最好(无同步开销)
* - 适用于单线程环境
*
* 性能对比:
* - 基本操作:普通数组 > AtomicIntegerArray > AtomicInteger
* - 线程安全:AtomicIntegerArray = AtomicInteger > 普通数组
* - 内存使用:AtomicIntegerArray < AtomicInteger[] < 普通数组
* - 功能丰富度:AtomicIntegerArray > 普通数组
*
* 选择建议:
* - 单个值:AtomicInteger
* - 整数数组:AtomicIntegerArray
* - 对象数组:AtomicReferenceArray
* - 单线程:普通数组
* - 需要版本控制:AtomicStampedReference
*
* 使用场景:
* - AtomicIntegerArray:计数器数组、状态数组、统计信息数组
* - AtomicInteger:单个计数器、序列号、简单的数值操作
* - AtomicReferenceArray:对象引用数组、缓存数组
* - 普通数组:单线程数据处理、临时存储
*/
8. 总结
AtomicIntegerArray 的核心特性:
-
数组原子操作:
- 提供对数组元素的原子操作
- 每个元素可以独立进行原子操作
- 支持细粒度的并发控制
-
无锁原子操作:
- 使用CAS实现原子性
- 避免传统锁的开销
- 提供乐观锁机制
-
内存可见性:
- 通过Unsafe的volatile操作保证可见性
- 确保多线程间的内存可见性
- 确保读操作获取最新值
-
丰富的原子操作:
- 基本的get/set操作
- 自增自减操作
- 比较并设置操作
- 函数式更新操作(Java 8+)
-
边界安全:
- 所有操作都进行索引边界检查
- 防止数组越界异常
- 提供安全的数组访问
-
高性能设计:
- 基于Unsafe的底层操作
- 数组偏移量直接访问
- 自旋重试机制
-
线程安全:
- 所有操作都是线程安全的
- 适用于高并发环境
- 无死锁风险
适用场景:
- 多线程环境下的计数器数组
- 状态标志数组
- 需要原子操作的整数数组
- 高并发环境下的数组操作
- 需要细粒度并发控制的场景
- 统计信息收集
- 缓存系统中的计数数组
注意事项:
- CAS操作可能出现ABA问题
- 高竞争场景下可能有自旋开销
- 不支持复合原子操作(需要多个步骤的原子操作)
- 需要正确处理CAS的返回值
- 注意选择合适的更新方法
- 始终进行边界检查
- 大数组可能占用较多内存
性能优化建议:
- 根据数据类型选择合适的原子数组类
- 合理使用compareAndSet避免不必要的操作
- 在高竞争场景下考虑减少竞争
- 监控原子操作的性能表现
- 避免频繁的原子操作
- 正确处理ABA问题(必要时使用版本控制)
- 选择合适的获取方法(getAnd系列 vs incrementAndGet系列)
- 使用局部变量减少数组访问
- 考虑使用更细粒度的并发控制