Java 标准库中提供了哪些原子操作类?

参考回答

Java 标准库中提供了一些原子操作类,它们位于 java.util.concurrent.atomic 包中,主要用于在多线程环境下执行线程安全的操作。这些类通过底层的 CAS(Compare-And-Swap) 操作来保证原子性,避免了使用传统的锁机制。

常见的原子操作类包括:

  1. AtomicInteger:提供对 int 类型的原子操作,如 get(), set(), incrementAndGet(), decrementAndGet(), addAndGet() 等。
  2. AtomicLong:提供对 long 类型的原子操作,类似于 AtomicInteger,但用于长整型。
  3. AtomicBoolean:提供对 boolean 类型的原子操作,支持基本的 get()set() 方法。
  4. AtomicReference:提供对对象引用的原子操作。它支持原子性的读取、修改、设置操作,适用于对象引用类型。
  5. AtomicIntegerArray:提供对 int[] 数组的原子操作。
  6. AtomicLongArray:提供对 long[] 数组的原子操作。
  7. AtomicReferenceArray:提供对对象数组的原子操作。
  8. AtomicMarkableReference:提供对对象引用的原子操作,支持标记位(boolean 值)来确保引用的原子性操作。
  9. 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) AtomicIntegerArrayAtomicLongArray

AtomicIntegerArrayAtomicLongArray 提供对 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) AtomicMarkableReferenceAtomicStampedReference
  • 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 标准库中提供的原子操作类包括:

  1. AtomicInteger
  2. AtomicLong
  3. AtomicBoolean
  4. AtomicReference
  5. AtomicIntegerArray
  6. AtomicLongArray
  7. AtomicReferenceArray
  8. AtomicMarkableReference
  9. AtomicStampedReference

发表评论

后才能评论