Java 标准库中提供了哪些原子操作类?
参考回答
Java 标准库中提供了一些原子操作类,它们位于 java.util.concurrent.atomic 包中,主要用于在多线程环境下执行线程安全的操作。这些类通过底层的 CAS(Compare-And-Swap) 操作来保证原子性,避免了使用传统的锁机制。
常见的原子操作类包括:
AtomicInteger:提供对int类型的原子操作,如get(),set(),incrementAndGet(),decrementAndGet(),addAndGet()等。AtomicLong:提供对long类型的原子操作,类似于AtomicInteger,但用于长整型。AtomicBoolean:提供对boolean类型的原子操作,支持基本的get()和set()方法。AtomicReference:提供对对象引用的原子操作。它支持原子性的读取、修改、设置操作,适用于对象引用类型。AtomicIntegerArray:提供对int[]数组的原子操作。AtomicLongArray:提供对long[]数组的原子操作。AtomicReferenceArray:提供对对象数组的原子操作。AtomicMarkableReference:提供对对象引用的原子操作,支持标记位(boolean值)来确保引用的原子性操作。AtomicStampedReference:类似于AtomicMarkableReference,但支持时间戳或版本号来解决 ABA 问题。
这些原子操作类是 无锁 的,通过 CAS 操作保证原子性,因此可以提高多线程应用的性能。
详细讲解与拓展
1. CAS(Compare-And-Swap)操作
CAS 是原子操作的核心,它通过比较内存中的当前值与预期值是否一致,如果一致则更新为新值,若不一致则不进行更新。CAS 操作是无锁的,避免了传统的锁机制带来的性能开销。
工作原理:
- 线程首先读取变量的当前值(比如
currentValue)。 - 然后与期望值(
expectedValue)进行比较,如果相等,则将值更新为新值(newValue)。 - 如果不相等,表示其他线程已经修改了该值,CAS 操作失败,线程会重新尝试获取最新的值并重新进行比较和更新。
public boolean compareAndSet(int expectedValue, int newValue) {
// CAS 操作的伪代码
int currentValue = value; // 获取当前值
if (currentValue == expectedValue) { // 比较
value = newValue; // 更新
return true; // 成功
}
return false; // 失败
}
2. 常见原子操作类及其功能
(1) AtomicInteger
AtomicInteger 提供了对 int 类型的原子操作,常用的方法包括:
get():获取当前值。set(int newValue):设置新值。incrementAndGet():将值加 1,并返回新值。decrementAndGet():将值减 1,并返回新值。addAndGet(int delta):将值加上delta,并返回新值。
示例:
AtomicInteger atomicInt = new AtomicInteger(0);
atomicInt.incrementAndGet(); // 返回 1
atomicInt.addAndGet(5); // 返回 6
(2) AtomicLong
AtomicLong 提供了对 long 类型的原子操作,方法与 AtomicInteger 类似,包括:
get():获取当前值。set(long newValue):设置新值。incrementAndGet():将值加 1,并返回新值。decrementAndGet():将值减 1,并返回新值。
示例:
AtomicLong atomicLong = new AtomicLong(0);
atomicLong.incrementAndGet(); // 返回 1
atomicLong.addAndGet(100L); // 返回 101
(3) AtomicBoolean
AtomicBoolean 提供对 boolean 类型的原子操作,常用方法包括:
get():获取当前值。set(boolean newValue):设置新值。compareAndSet(boolean expectedValue, boolean newValue):如果当前值是预期值,则设置为新值。
示例:
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
atomicBoolean.set(true); // 设置为 true
atomicBoolean.compareAndSet(true, false); // 从 true 改为 false
(4) AtomicReference
AtomicReference 提供了对引用类型的原子操作,支持对象引用的原子更新,常用方法包括:
get():获取当前引用。set(V newValue):设置新引用。compareAndSet(V expectedValue, V newValue):如果当前值是预期值,则设置为新引用。
示例:
AtomicReference<String> atomicRef = new AtomicReference<>("Hello");
atomicRef.set("World"); // 设置新值
atomicRef.compareAndSet("World", "Java"); // 将 "World" 替换为 "Java"
(5) AtomicIntegerArray 和 AtomicLongArray
AtomicIntegerArray 和 AtomicLongArray 提供对 int[] 和 long[] 数组的原子操作。常用方法包括:
get(int index):获取指定索引的值。set(int index, int newValue):设置指定索引的新值。getAndSet(int index, int newValue):获取当前值并设置为新值。
示例:
AtomicIntegerArray array = new AtomicIntegerArray(new int[10]);
array.set(0, 100); // 设置第一个元素为 100
array.incrementAndGet(0); // 第一个元素加 1
(6) AtomicMarkableReference 和 AtomicStampedReference
AtomicMarkableReference:它不仅支持对象的原子引用更新,还允许对每个对象引用进行标记(boolean标记),适用于一些特定的并发场景,例如标记操作成功与否。AtomicStampedReference:它支持对象引用和版本号的原子更新,解决了CAS中的 ABA 问题。
示例:
AtomicStampedReference<String> stampedRef = new AtomicStampedReference<>("Hello", 0);
int[] stamp = new int[1];
String current = stampedRef.get(stamp); // 获取当前值和版本号
stampedRef.compareAndSet("Hello", "World", stamp[0], stamp[0] + 1); // 使用版本号进行更新
总结
Java 标准库中提供的原子操作类包括:
AtomicIntegerAtomicLongAtomicBooleanAtomicReferenceAtomicIntegerArrayAtomicLongArrayAtomicReferenceArrayAtomicMarkableReferenceAtomicStampedReference