Java 原子类包括以下几种类型:
AtomicInteger 是 Java 并发包中提供的一个原子类,用于实现原子性操作的整型变量。它的原理是利用了 CPU 提供的原子性操作指令,通过 CAS(Compare and Swap)算法实现原子性操作。
CAS 算法是一种无锁算法,通过比较当前内存地址的值与期望值是否相等,如果相等则将新的值写入该内存地址,否则不做任何操作。CAS 算法的基本操作包括三个参数:内存地址 V、期望值 A 和新值 B。如果 V 的值等于 A,则将 V 的值修改为 B,否则不做任何操作。CAS 算法的实现通常由硬件层面提供支持,可以保证原子性操作的高效性和正确性。
在 AtomicInteger 类中,原子性操作的实现就是利用了 CAS 算法。例如,对于 AtomicInteger 的 incrementAndGet() 方法,其实现大致如下:
1. 获取当前 AtomicInteger 的值 value。
2. 将 value 和 1 相加,得到新的值 newValue。
3. 利用 CAS 算法,将内存地址 V 的值与期望值 A(即原来的 value)比较,如果相等,则将 V 的值修改为新值 B(即 newValue),并返回修改后的值。
4. 如果 CAS 操作失败,则重新执行步骤 1 到 3,直到 CAS 操作成功为止。
通过这种方式,AtomicInteger 类可以实现原子性的自增、自减、比较和交换等操作,避免了多线程环境下的数据竞争问题。同时,由于 CAS 算法是一种无锁算法,因此可以避免了锁的开销和竞争带来的性能损失,具有较好的性能和可伸缩性。
AtomicInteger 是 Java 中用于实现原子性操作的类之一,其源码主要包含以下几个方面:
private volatile int value;
public AtomicInteger() {
this(0);
}
public AtomicInteger(int initialValue) {
value = initialValue;
}
public final int get() {
return value;
}
public final void set(int newValue) {
value = newValue;
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
以上是 AtomicInteger 类的主要方法和字段,它们都是基于 CAS(Compare and Swap)算法实现的,保证了在多线程环境下的原子性操作。
AtomicIntegerArray 是 Java 并发包中提供的一个原子操作类,可以实现对整型数组的原子操作。它的原理是通过底层调用 sun.misc.Unsafe 类的方法来实现对数组元素的 CAS 操作,从而保证多线程并发访问时的数据安全。
具体来说,AtomicIntegerArray 中的核心方法包括 get、set、getAndAdd、getAndIncrement、getAndDecrement、getAndSet 和 compareAndSet 等。其中,get 和 set 方法分别用于获取和设置指定下标的数组元素的值,它们不涉及原子操作;getAndAdd、getAndIncrement、getAndDecrement 和 getAndSet 方法则是进行原子操作的方法,它们都是通过 do-while 循环不断尝试 CAS 操作,直到成功为止,然后返回旧值;compareAndSet 方法是进行原子操作的核心方法,它使用 Unsafe 类的 compareAndSwapInt() 方法来实现 CAS 操作,如果操作成功则返回 true,否则返回 false。
为了实现对数组元素的 CAS 操作,AtomicIntegerArray 中使用了 sun.misc.Unsafe 类的一些方法,包括 compareAndSwapInt、arrayBaseOffset 和 arrayIndexScale 等。其中,compareAndSwapInt 方法是用于实现 CAS 操作的方法,它的作用是比较指定位置的数组元素的值是否等于期望值,如果相等则将其设为新值,返回操作是否成功的布尔值;arrayBaseOffset 和 arrayIndexScale 方法则是用于计算数组元素的地址偏移量的方法,它们分别返回数组在内存中的基地址和元素之间的偏移量,从而可以计算出数组元素在内存中的地址偏移量,方便进行 CAS 操作。
总之,AtomicIntegerArray 的原理是通过底层调用 Unsafe 类的方法实现对整型数组的原子操作,从而保证多线程并发访问时的数据安全。
public class AtomicIntegerArray implements java.io.Serializable {
private static final long serialVersionUID = 2862133569453604235L;
// 数组元素,使用 volatile 修饰以保证内存可见性
private final int[] array;
// 构造方法,将传入的数组复制一份作为 AtomicIntegerArray 的数组元素
public AtomicIntegerArray(int length) {
array = new int[length];
}
// 构造方法,将传入的数组复制一份作为 AtomicIntegerArray 的数组元素
public AtomicIntegerArray(int[] array) {
this.array = array.clone();
}
// 获取指定下标的数组元素的值
public final int get(int i) {
return array[i];
}
// 设置指定下标的数组元素的值
public final void set(int i, int newValue) {
array[i] = newValue;
}
// 获取指定下标的数组元素的值,并将其加上指定的 delta 值
public final int getAndAdd(int i, int delta) {
// do-while 循环,直到 CAS 成功为止
int oldValue;
do {
oldValue = get(i); // 获取当前值
} while (!compareAndSet(i, oldValue, oldValue + delta)); // 比较并交换,如果失败则继续循环
return oldValue; // 返回旧值
}
// 获取指定下标的数组元素的值,并将其加上 1
public final int getAndIncrement(int i) {
return getAndAdd(i, 1);
}
// 获取指定下标的数组元素的值,并将其减去 1
public final int getAndDecrement(int i) {
return getAndAdd(i, -1);
}
// 获取指定下标的数组元素的值,并将其设为指定的 newValue 值
public final int getAndSet(int i, int newValue) {
// do-while 循环,直到 CAS 成功为止
int oldValue;
do {
oldValue = get(i); // 获取当前值
} while (!compareAndSet(i, oldValue, newValue)); // 比较并交换,如果失败则继续循环
return oldValue; // 返回旧值
}
// 比较指定下标的数组元素的值是否等于 expect,如果相等则将其设为 update
public final boolean compareAndSet(int i, int expect, int update) {
// 使用 unsafe.compareAndSwapInt() 方法实现 CAS 操作
return unsafe.compareAndSwapInt(array, byteOffset(i), expect, update);
}
// 获取数组元素在数组中的偏移量(即下标乘以元素大小)
private static int byteOffset(int i) {
return i << 2; // 相当于 i * 4
}
// 获取 Unsafe 实例,用于实现 CAS 操作
private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
private static final long base = unsafe.arrayBaseOffset(int[].class);
private static final long 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);
}
// 计算数组元素在内存中的地址偏移量
private static long calcLongOffset(int i) {
return ((long) i << shift) + base;
}
}
AtomicLongFieldUpdater 是 Java 并发包中提供的一种工具类,用于实现对某个对象的 long 类型字段的原子操作。它可以让我们利用原子性操作实现对共享变量的高效访问,避免使用锁机制带来的性能损耗和死锁问题。
AtomicLongFieldUpdater 的实现原理是利用反射机制和 CAS(Compare-And-Swap)操作实现对共享变量的原子操作。具体来说,AtomicLongFieldUpdater 类通过反射机制访问对象的 long 类型字段,然后调用 Unsafe 类的 compareAndSwapLong 方法,实现对字段的原子操作。
CAS 操作是一种原子性操作,它可以保证多线程并发访问时的数据安全。CAS 操作的基本思想是,先获取共享变量的当前值,然后比较这个值是否等于期望值,如果相等,则将共享变量的值设为新值,否则不做任何操作。如果多个线程同时尝试对同一个共享变量进行 CAS 操作,只有一个线程能够成功,其他线程将会失败,需要重新尝试。
AtomicLongFieldUpdater 利用 CAS 操作实现了对共享变量的原子操作。例如,可以通过 AtomicLongFieldUpdater 对某个类的 long 类型字段进行原子操作,而不需要使用锁机制。
需要注意的是,使用 AtomicLongFieldUpdater 操作字段时,要求该字段必须是 volatile 类型的,否则可能会出现数据不一致的问题。
总之,AtomicLongFieldUpdater 是 Java 并发包中提供的一种工具类,它利用反射机制和 CAS 操作实现对某个对象的 long 类型字段的原子操作,可以提高多线程并发访问的性能和安全性。
public abstract class AtomicLongFieldUpdater {
// 获取一个对象的 long 类型字段的值
public abstract long get(T obj);
// 设置一个对象的 long 类型字段的值
public abstract void set(T obj, long newValue);
// 比较并设置一个对象的 long 类型字段的值,如果当前值等于期望值,则设置为新值
public abstract boolean compareAndSet(T obj, long expect, long update);
// 弱化版的 compareAndSet,不保证成功设置字段值,但执行效率更高
public abstract boolean weakCompareAndSet(T obj, long expect, long update);
// 对一个对象的 long 类型字段进行增加操作,并返回新的值
public abstract long getAndAdd(T obj, long delta);
// 对一个对象的 long 类型字段进行增加操作,并返回新的值
public abstract long addAndGet(T obj, long delta);
// 创建一个 AtomicLongFieldUpdater 实例,用于更新指定类的指定字段
public static AtomicLongFieldUpdater newUpdater(Class tclass, String fieldName) {
// 参数校验
if (tclass == null || fieldName == null) {
throw new NullPointerException();
}
// 获取字段的反射对象
final Field field;
try {
field = tclass.getDeclaredField(fieldName);
if (!Modifier.isVolatile(field.getModifiers())) {
throw new IllegalArgumentException("Must be volatile");
}
Class<?> fieldType = field.getType();
if (fieldType != long.class) {
throw new IllegalArgumentException("Must be long type");
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
// 创建 AtomicLongFieldUpdaterImpl 实例
return new AtomicLongFieldUpdaterImpl(field);
}
}
class AtomicLongFieldUpdaterImpl extends AtomicLongFieldUpdater {
// 字段的偏移量
private final long offset;
// 构造方法,通过反射获取字段的偏移量
AtomicLongFieldUpdaterImpl(Field field) {
// 参数校验
if (!Modifier.isVolatile(field.getModifiers())) {
throw new IllegalArgumentException("Must be volatile");
}
Class<?> fieldType = field.getType();
if (fieldType != long.class) {
throw new IllegalArgumentException("Must be long type");
}
// 获取字段的偏移量
this.offset = unsafe.objectFieldOffset(field);
}
// 获取一个对象的 long 类型字段的值
public long get(T obj) {
return unsafe.getLongVolatile(obj, offset);
}
// 设置一个对象的 long 类型字段的值
public void set(T obj, long newValue) {
unsafe.putLongVolatile(obj, offset, newValue);
}
// 比较并设置一个对象的 long 类型字段的值,如果当前值等于期望值,则设置为新值
public boolean compareAndSet(T obj, long expect, long update) {
return unsafe.compareAndSwapLong(obj, offset, expect, update);
}
// 弱化版的 compareAndSet,不保证成功设置字段值,但执行效率更高
public boolean weakCompareAndSet(T obj, long expect, long update) {
return unsafe.compareAndSwapLong(obj, offset, expect, update);
}
// 对一个对象的 long 类型字段进行增加操作,并返回新的值
public long getAndAdd(T obj, long delta) {
long current, next;
do {
current = get(obj);
next = current + delta;
} while (!compareAndSet(obj, current, next));
return current;
}
// 对一个对象的 long 类型字段进行增加操作,并返回新的值
public long addAndGet(T obj, long delta) {
long current, next;
do {
current = get(obj);
next = current + delta;
} while (!compareAndSet(obj, current, next));
return next;
}
}
AtomicLongFieldUpdater 是一个抽象类,用于实现对某个对象的 long 类型字段的原子操作。该类的主要方法包括 get、set、compareAndSet、weakCompareAndSet、addAndGet 和 getAndAdd 等,通过反射机制和 Unsafe 类实现对共享变量的原子操作。
小结:
小心这些原子类中的set和get方法。没有使用cas就不保证原子性了,只能保证可见性和有序性。
页面更新:2024-04-29
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号