Java 8下实现Compare And Exchange(非Compare and Set)的方案问询
在Java 8中实现AtomicReference的compareAndExchange与compareAndExchangeWeak
实现compareAndExchange
Java 8的AtomicReference没有内置compareAndExchange,但可以基于它的get()和compareAndSet()方法原子性地实现该逻辑,核心是通过循环处理CAS失败的情况,最终返回操作前的原有值:
import java.util.concurrent.atomic.AtomicReference; public class AtomicReferenceUtils { public static <V> V compareAndExchange(AtomicReference<V> ref, V expected, V newValue) { V current; do { current = ref.get(); // 当前值不符合预期,直接跳出循环返回 if (current != expected) { break; } // 符合预期则尝试CAS,失败则循环重试 } while (!ref.compareAndSet(expected, newValue)); return current; } }
逻辑说明:
ref.get()是volatile读,保证能获取到最新的内存值- 若当前值
current与expected不相等,直接返回current(无需执行CAS) - 若相等则尝试原子更新,更新失败说明其他线程修改了值,重新获取最新值并重试
- 最终返回的
current就是操作发起时的"见证值",无论CAS是否成功,都严格符合compareAndExchange的语义
实现compareAndExchangeWeak
compareAndExchangeWeak允许虚假失败(即当前值符合预期时,CAS也可能因底层硬件原因失败),因此不需要内部循环,只执行一次CAS尝试即可,适合在外部循环中使用(由调用方处理重试):
import java.util.concurrent.atomic.AtomicReference; public class AtomicReferenceUtils { public static <V> V compareAndExchangeWeak(AtomicReference<V> ref, V expected, V newValue) { V current = ref.get(); if (current == expected) { // 仅尝试一次CAS,允许虚假失败 ref.compareAndSet(expected, newValue); } return current; } }
逻辑说明:
- 同样通过volatile读获取当前值
current - 若
current与expected相等,仅执行一次CAS操作,不处理失败情况 - 直接返回
current,无论CAS是否成功 - 这个版本的开销更低,虚假失败可以通过外层循环弥补,是高并发场景下的更优选择(比如在自旋锁中使用)
关键注意事项
- 保持语义一致性:实现中使用
==进行引用比较,与AtomicReference原生CAS方法的语义完全一致(若需要值比较,可替换为Objects.equals()) - 原子性保证:依赖
AtomicReference的compareAndSet()的原子性,确保整个操作符合并发安全要求 - 无第三方依赖:完全基于Java 8标准库实现,满足项目环境限制
内容的提问来源于stack exchange,提问作者李浩穎
相关产品推荐
相关产品推荐

