Java中用AtomicReference实现无锁更新,核心是将成员变量声明为final AtomicReference类型,通过compareAndSet等原子方法替代直接赋值;compareAndSet用于条件更新需循环重试,getAndSet/updateAndGet适用于无条件更新;其CAS基于引用相等而非内容相等。

Java 中用 AtomicReference 实现成员变量的无锁更新,核心是把普通成员变量替换成 AtomicReference 类型,并用其原子方法(如 compareAndSet、getAndSet)替代直接赋值,避免显式加锁。
把成员变量声明为 AtomicReference
不是给已有变量加锁,而是从设计之初就用原子引用封装数据。例如原本的普通对象引用:
// 传统写法(非线程安全)
private User currentUser;
// 改为原子引用
private final AtomicReference
注意:建议声明为 final,保证引用本身不可变,只让其内部值原子更新。
用 compareAndSet 实现条件更新
这是最典型的无锁更新模式,适用于“检查-修改”场景(CAS 操作):
- 先读取当前值(
get()) - 基于当前值计算新值
- 用
compareAndSet(expected, updated)原子尝试更新 - 失败则重试(通常用循环)
例如更新用户积分:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
public void addPoints(int delta) {
User current;
User updated;
do {
current = currentUser.get();
updated = new User(current.getName(), current.getPoints() + delta);
} while (!currentUser.compareAndSet(current, updated));
}
用 getAndSet 或 updateAndGet 简化常见操作
如果不需要条件判断,只是覆盖或函数式更新,可直接用更简洁的方法:
-
getAndSet(newVal):原子地设置新值并返回旧值(类似锁中 swap) -
updateAndGet(unaryOperator):传入一个函数,原子地读-改-写(JDK 1.8+) -
accumulateAndGet(x, accumulator):适合数值类累积(需类型支持,如AtomicInteger更常用;对引用类型需自行实现合并逻辑)
例如强制切换当前用户:
public void switchToUser(User newUser) {
currentUser.getAndSet(newUser);
}
注意引用相等性与对象语义
AtomicReference 的 compareAndSet 默认比较的是引用相等(==),不是内容相等(.equals())。这意味着:
- 如果每次创建新对象(如
new User(...)),即使内容相同,引用也不同,CAS 会成功——这通常是期望行为 - 但如果复用对象或使用不可变类,要确保“相同逻辑状态”的对象不被误判为不同引用
- 必要时可包装逻辑判断,但不能绕过 CAS 的引用语义;想按内容 CAS 需自行实现乐观锁逻辑(如版本号字段)
无锁不是万能的,它依赖正确建模更新逻辑,且高竞争下可能因反复重试影响吞吐——但多数场景下比 synchronized 更轻量。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










