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 标准库中提供的原子操作类包括:
AtomicInteger
AtomicLong
AtomicBoolean
AtomicReference
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
AtomicMarkableReference
AtomicStampedReference