compareAndExchange是Java 9新增的原子操作,总是返回当前内存中的实际值(见证值),无论交换是否成功;而compareAndSet仅返回布尔结果,无法获知失败时的实际值。

Java 9 起,AtomicReference 新增了 compareAndExchange 方法,它不是对 compareAndSet 的简单增强,而是提供了一种更底层、更透明的原子读-改-写语义。
compareAndExchange 是什么
该方法执行一次原子性的“比较并交换”,但关键在于:它**总是返回当前内存中的实际值(见证值)**,无论交换是否成功。这个行为由 VarHandle.compareAndExchange 规范定义,保证内存效果与 VarHandle 一致。
- 如果当前值等于
expectedValue,则更新为newValue,并返回该expectedValue - 如果当前值不等于
expectedValue,则不做修改,仍返回此时的实际值(即“被别人抢先改过的值”或“原本就不同的值”)
和 compareAndSet 的核心区别
compareAndSet(expected, desired) 只返回 boolean:成功为 true,失败为 false;你无法知道失败时“现在到底是什么值”。而 compareAndExchange 始终返回那个“现在是什么值”,让调用方掌握完整上下文。
- 失败时,你可以直接拿到最新值,用于重试决策、版本比对或日志诊断
- 无需额外调用
get()获取当前值,避免两次 volatile 读带来的开销和中间态风险 - 返回值类型严格匹配泛型类型,无装箱/拆箱,比
AtomicInteger.compareAndSet(int, int)更安全
典型使用模式
不能忽略返回值——这是正确使用的前提。常见写法是显式比对返回值:
立即学习“Java免费学习笔记(深入)”;
- 判断是否成功:
if (handle.compareAndExchange(obj, old, new) == old) { /* 成功 */ } - 获取真实当前值:
Object current = handle.compareAndExchange(obj, old, new); if (!current.equals(old)) { /* 处理竞争,current 就是最新值 */ } - 配合乐观锁版本控制:交换失败后,用返回的
current提取版本号,决定是否重试或降级
适用场景与注意事项
适合需要“原子读取旧值 + 条件更新 + 立即响应当前状态”的逻辑,比如限流计数器、状态机跃迁、带版本的缓存更新。
- 不适用于仅需“试试看,成功就走,失败就算了”的简单场景——此时
compareAndSet更简洁 - 必须用之前
get()拿到的**同一引用对象**作为expected,不能新建等价对象(==判断) - 在
AtomicReferenceArray和字段更新器中也存在同名方法,语义一致,只是操作目标不同


















