You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者李浩穎

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 11:15:32