AtomicReference 和 volatile 的比较
AtomicReference 和 volatile 都是 Java 中用于处理多线程环境下变量可见性和原子性的机制,但它们在功能和使用场景上有重要区别。
volatile 关键字
特点:
-
保证变量的可见性:一个线程对 volatile 变量的修改会立即对其他线程可见
-
禁止指令重排序:防止 JVM 和处理器对指令进行重排序优化
-
不保证原子性:对 volatile 变量的复合操作(如 i++)不是原子性的
适用场景:
-
简单的标志位(boolean 状态标志)
-
单线程写,多线程读的场景
-
对变量的操作本身就是原子性的情况
示例:
private volatile boolean flag = false;public void setFlag() {flag = true;
}public boolean isFlagSet() {return flag;
}
AtomicReference 类
特点:
-
提供原子性的引用更新操作
-
内部使用 CAS (Compare-And-Swap) 操作保证原子性
-
可以用于构建更复杂的无锁算法
-
提供了丰富的原子操作方法(如 compareAndSet, getAndSet 等)
适用场景:
-
需要原子性地更新对象引用
-
需要实现无锁(lock-free)算法
-
需要保证复合操作的原子性
示例:
private final AtomicReference<String> ref = new AtomicReference<>("Initial");public void updateValue(String newValue) {String oldValue = ref.get();while (!ref.compareAndSet(oldValue, newValue)) {oldValue = ref.get();}}
主要区别
特性 | volatile | AtomicReference |
---|---|---|
可见性 | 保证 | 保证 |
原子性 | 不保证复合操作 | 保证引用更新的原子性 |
复合操作 | 不支持 | 支持(如 compareAndSet) |
性能 | 较高 | 略低(因 CAS 操作) |
使用场景 | 简单状态标志 | 复杂原子操作 |
内存屏障 | 读写都有内存屏障 | 通过 Unsafe 类实现内存语义 |
如何选择
-
如果只需要保证变量的可见性,使用
volatile
-
如果需要原子性地更新对象引用或实现更复杂的原子操作,使用
AtomicReference
-
在高度竞争的环境下,
volatile
性能可能更好,但功能有限 -
需要无锁编程时,
AtomicReference
是更好的选择