AtomicReference
是 Java java.util.concurrent.atomic
包中的核心类之一,用于在多线程环境下实现线程安全的对象引用原子操作。本文将结合 JDK 8 源码,从底层实现、核心方法、设计模式等角度深入解析其原理。
AtomicReference
是泛型类(
表示引用对象的类型),实现了 java.io.Serializable
(支持序列化):
public class AtomicReference<V> implements java.io.Serializable {
// ... 核心字段与方法 ...
}
Unsafe
与 CAS
基础AtomicReference
的原子性依赖以下核心字段:
private static final Unsafe unsafe
:通过 Unsafe.getUnsafe()
获取的底层操作工具类,提供硬件级别的原子操作(如 CAS
)。private static final long valueOffset
:通过 Unsafe.objectFieldOffset
反射获取的 value
字段在内存中的偏移量(用于 CAS
操作定位内存地址)。private volatile V value
:实际存储对象引用的变量,volatile
保证多线程间的可见性(修改后立即被其他线程感知)。private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
// 反射获取 value 字段的内存偏移量
valueOffset = unsafe.objectFieldOffset(AtomicReference.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private volatile V value; // 实际存储的对象引用,volatile 保证可见性
AtomicReference
的原子性通过 CAS
(Compare-And-Swap
)算法实现,其逻辑与 AtomicInteger
类似,但操作对象是对象引用而非基本类型。
get
/set
get()
:直接返回 value
的当前引用(依赖volatile
保证可见性)。set(V newValue)
:直接修改 value
(同样依赖 volatile
保证可见性)。lazySet(V newValue)
:通过 Unsafe.putOrderedObject
实现延迟设置,不保证立即对其他线程可见(适用于非关键的最终一致性场景)。CAS
直接调用compareAndSet(V expect, V update)
是核心原子方法,直接调用 Unsafe.compareAndSwapObject
实现 CAS
:
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
expect
是预期的旧引用,update
是目标新引用。true
,否则 false
(说明有其他线程修改了引用)。getAndSet
getAndSet(V newValue)
原子性地设置新值并返回旧值,底层调用 Unsafe.getAndSetObject
:
@SuppressWarnings("unchecked")
public final V getAndSet(V newValue) {
return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
}
Unsafe.getAndSetObject
的底层逻辑是循环执行 CAS
,直到成功替换引用。
JDK8 引入了 UnaryOperator
和 BinaryOperator
函数式接口,支持自定义原子更新逻辑,例如 getAndUpdate
:
public final V getAndUpdate(UnaryOperator<V> updateFunction) {
V prev, next;
do {
prev = get(); // 获取当前引用
next = updateFunction.apply(prev); // 应用自定义函数计算新引用
} while (!compareAndSet(prev, next)); // 循环 CAS 直到成功
return prev; // 返回旧引用
}
CAS
)固定,具体的更新逻辑由用户传入的函数决定,符合模板方法模式(Template Method Pattern)。AtomicReference
的实现中隐含了两种关键设计模式:
AtomicReference
的大部分原子方法(如 compareAndSet
、getAndSet
)本质上是对 Unsafe
类对应方法的代理。Unsafe
提供了底层的 CAS
操作,而 AtomicReference
封装了这些操作,提供更易用的业务接口。
优点:隔离底层实现细节,降低用户使用复杂度。
JDK8 新增的函数式方法(如 getAndUpdate
、accumulateAndGet
)定义了原子操作的骨架流程(循环获取当前引用 → 计算新引用 → CAS 更新),具体的计算逻辑由用户传入的函数式接口实现。
优点:灵活扩展原子操作的逻辑,同时保证原子性的核心流程不变。
优点
synchronized
的阻塞机制,CAS
是乐观锁,避免了线程上下文切换开销。缺点
A→B→A
,CAS
会误判为未修改。可通过 AtomicStampedReference
(带版本号)或 AtomicMarkableReference
(带标记)解决。CAS
可能频繁重试,导致性能下降(此时 synchronized
可能更优)。AtomicReference
是 Java 并发编程中实现对象引用原子操作的核心工具,其设计思想可总结为:
通过 volatile
保证可见性 + Unsafe
提供的 CAS
保证原子性,结合代理模式和模板方法模式,封装出易用、高效的线程安全对象引用操作类。理解其源码有助于深入掌握 Java 并发编程的底层逻辑,以及无锁算法在对象引用场景中的应用。