volatile不能直接实现观察者模式,仅保证可见性和禁止重排序,不提供原子性或事件通知机制;适合状态标志等单写多读场景,复杂逻辑应使用copyonwritearraylist等线程安全工具配合显式通知。

volatile 不能直接实现观察者模式的状态同步,它只保证可见性和禁止指令重排序,不提供原子性或线程安全的事件通知机制。 如果强行用 volatile 实现“简易观察者”,只能用于极轻量、单写多读、无竞态逻辑的场景(比如开关标志位),且必须配合轮询或外部触发——这不是标准观察者模式,也不推荐在生产中使用。
volatile 的真实作用:可见性保障
当一个线程修改了 volatile 字段,其他线程能立即看到最新值。但它不保证操作的原子性(如 counter++ 是读-改-写三步,volatile 无法保护);也不触发回调或通知,观察者不会自动得知变化。
- 适合场景:状态标志(如
running = true/false)、初始化完成标记(initialized) - 不适合场景:需要响应变化执行业务逻辑、维护多个依赖状态、有复杂更新逻辑
用 volatile 模拟“简易观察”(仅限轮询式)
若坚持用 volatile,可让观察者主动轮询 volatile 变量,发现变化后自行处理。例如:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
public class SimpleSubject {
private volatile int state = 0;
public void setState(int newState) {
this.state = newState; // 写入立即对其他线程可见
}
public int getState() {
return state; // 读取总是最新值
}
}
// 观察者需自行轮询(不推荐,浪费 CPU)
public class PollingObserver implements Runnable {
private final SimpleSubject subject;
private int lastSeen = -1;
public PollingObserver(SimpleSubject subject) {
this.subject = subject;
}
@Override
public void run() {
while (true) {
int current = subject.getState();
if (current != lastSeen) {
System.out.println("State changed to: " + current);
lastSeen = current;
}
try {
Thread.sleep(10); // 避免忙等
} catch (InterruptedException e) {
break;
}
}
}
}
- 缺点明显:轮询低效、延迟不可控、无法区分变化原因、难以管理多个观察者
- volatile 在这里只解决了“读到新值”的问题,其余全是手动补足
真正推荐的做法:用线程安全容器 + 显式通知
要可靠实现观察者模式,应结合 volatile(用于状态快照)和真正的同步机制:
- 用
CopyOnWriteArrayList存储观察者列表(线程安全,遍历时不怕并发修改) - 用 volatile 标记“是否已发布”或“当前有效状态”,供快速判断
- 在
notifyObservers()中遍历并调用回调,确保事件按需分发
public class SafeSubject {
private volatile int currentState = 0;
private final List<consumer>> observers = new CopyOnWriteArrayList();
public void addObserver(Consumer<integer> observer) {
observers.add(observer);
}
public void setState(int newState) {
this.currentState = newState;
notifyObservers(newState); // 主动通知,非轮询
}
private void notifyObservers(int state) {
for (Consumer<integer> obs : observers) {
obs.accept(state); // 在当前线程同步调用
}
}
}</integer></integer></consumer>
小结:volatile 是配角,不是主角
volatile 是 JVM 提供的轻量级同步工具,适合做状态信号灯;但观察者模式的核心是“变更通知+解耦回调”,这需要显式的事件分发机制。硬套 volatile 不仅代码难维护,还容易掩盖竞态风险。生产环境请优先选择 java.util.concurrent 工具类、ReentrantLock、或成熟的事件总线(如 Guava EventBus、Spring ApplicationEvent)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










