数组类型的原子类
类名 | 说明 |
---|---|
AtomicIntegerArray | 原子更新整型数组里的元素。 |
AtomicLongArray | 原子更新长整型数组里的元素。 |
AtomicReferenceArray | 原子更新引用类型数组的元素。 |
AtomicBooleanArray | 原子更新布尔类型数组的元素。 |
AtomicIntegerArray
AtomicIntegerArray 主要时用来封装对数组中某个元素操作。
原理解析
AtomicIntegerArray 对数组元素的操作使用Unsafe类两个重要的方法
- arrayBaseOffset:获取该类型的数组,在对象存储时,存放第一个元素的内存地址
- arrayIndexScale: 返回数组中每一个元素占用的大小
当我知道了起始位置,每一个元素的大小就可以推算出数组中每个元素对应偏移位置。那么只需要使用unsafe对数组对象操作方法设置值。
private static final Unsafe unsafe = Unsafe.getUnsafe();
/** 获取该类型的数组,在对象存储时,存放第一个元素的内存地址 **/
private static final int base = unsafe.arrayBaseOffset(int[].class);
/** 用于计算数组中每个元素的偏移位置 **/
private static final int shift;
/** 操作对象 **/
private final int[] array;
static {
/** 返回数组中每一个元素占用的大小(int类型返回4)**/
int scale = unsafe.arrayIndexScale(int[].class);
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
/** 返回 scale 高位连续0的个数(int 类型返回2) **/
shift = 31 - Integer.numberOfLeadingZeros(scale);
}
/**
* 获取数组中每个元素的偏移位置(存在校验)
*/
private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
return byteOffset(i);
}
/**
* 获取数组中每个元素的偏移位置
*/
private static long byteOffset(int i) {
return ((long) i << shift) + base;
}
对数组元素的操作
/**
* 使用CAS将位置{@code i}的元素设置为给定值newValue,成功返回true,失败返回false
*/
public final boolean compareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
private boolean compareAndSetRaw(long offset, int expect, int update) {
return unsafe.compareAndSwapInt(array, offset, expect, update);
}
源码解析
构造方法
/**
* 实例化一个AtomicIntegerArray,设置素组大小
*/
public AtomicIntegerArray(int length) {
array = new int[length];
}
/**
* 创建一个新的AtomicIntegerArray,并给定一个数组初始化
*/
public AtomicIntegerArray(int[] array) {
// Visibility guaranteed by final field guarantees
this.array = array.clone();
}
原子操作
/**
* 获取位置{@code i}的当前值。
*/
public final int get(int i) {
return getRaw(checkedByteOffset(i));
}
private int getRaw(long offset) {
return unsafe.getIntVolatile(array, offset);
}
/**
* 将位置{@code i}的元素设置为给定值。
*/
public final void set(int i, int newValue) {
unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
}
/**
将位置{@code i}的元素设置为给定值newValue(不保证其他线程立刻看到),
因为value设置为volatile一般情况下其他线程都可见,这里就是抛弃了volatile特性,
1 清空其他线程中缓存,保证可见性
2 内存屏障保证有序性。
*
*/
public final void lazySet(int i, int newValue) {
unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
}
/**
* 原子方式将位置{@code i}的元素设置为给定值newValue并返回旧值。(内部使用CAS乐观锁+循环)
*/
public final int getAndSet(int i, int newValue) {
return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
}
/**
* 使用CAS将位置{@code i}的元素设置为给定值newValue,成功返回true,失败返回false
*/
public final boolean compareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
private boolean compareAndSetRaw(long offset, int expect, int update) {
return unsafe.compareAndSwapInt(array, offset, expect, update);
}
/**
* 使用CAS将位置{@code i}的元素设置为给定值newValue,成功返回true,失败返回false
*/
public final boolean weakCompareAndSet(int i, int expect, int update) {
return compareAndSet(i, expect, update);
}
/**
* 以原子方式将位置{@code i}的元素+1。(内部使用CAS乐观锁+循环),返回旧值
*/
public final int getAndIncrement(int i) {
return getAndAdd(i, 1);
}
/**
* 以原子方式将位置{@code i}的元素-1。(内部使用CAS乐观锁+循环),返回旧值
*/
public final int getAndDecrement(int i) {
return getAndAdd(i, -1);
}
/**
* 以原子方式将位置{@code i}的元素+delta。这里传入负数就是减少|delta|(内部使用CAS乐观锁+循环),返回旧值
*/
public final int getAndAdd(int i, int delta) {
return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
}
/**
* 以原子方式将位置{@code i}的元素+1。(内部使用CAS乐观锁+循环),返回新值
*/
public final int incrementAndGet(int i) {
return getAndAdd(i, 1) + 1;
}
/**
* 以原子方式将位置{@code i}的元素-1。(内部使用CAS乐观锁+循环),返回新值
*/
public final int decrementAndGet(int i) {
return getAndAdd(i, -1) - 1;
}
/**
* 以原子方式将位置{@code i}的元素+delta。这里传入负数就是减少|delta|(内部使用CAS乐观锁+循环),返回新值
*/
public final int addAndGet(int i, int delta) {
return getAndAdd(i, delta) + delta;
}
/**
* 以原子方式将位置{@code i}的元素+执行IntUnaryOperator函数处理,使用CAS乐观锁+循环,返回旧值
*/
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;
}
/**
* 以原子方式将位置{@code i}的元素+执行IntUnaryOperator函数处理,使用CAS乐观锁+循环,返回新值
*/
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;
}
/**
* 以原子方式将位置{@code i}的元素+执行IntBinaryOperator函数处理,使用CAS乐观锁+循环,返回旧值
*/
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;
}
/**
* 以原子方式将位置{@code i}的元素+执行IntBinaryOperator函数处理,使用CAS乐观锁+循环,返回新值
*/
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;
}
AtomicLongArray,AtomicReferenceArray,AtomicBooleanArray实现和AtomicIntegerArray实现基本相同就不再详诉。
网友评论