volatile关键字用于保证变量的内存可见性和禁止指令重排序,适用于多线程下标志位控制等场景,但不保证复合操作的原子性,需配合锁或原子类使用。

在Java中,volatile关键字用于确保变量的内存可见性,是多线程编程中一个重要的轻量级同步机制。它不能保证原子性,但能保证一个线程对变量的修改立即被其他线程看到。
volatile的作用:内存可见性
Java内存模型(JMM)规定,每个线程都有自己的工作内存(缓存),线程操作变量时通常从主内存复制到工作内存进行读写,之后再写回主内存。这可能导致一个线程修改了变量,但其他线程看不到最新值。
当一个变量被声明为volatile,JVM会保证:
- 每次读取该变量时,都从主内存中获取最新值
- 每次写入该变量后,立即刷新到主内存
- 禁止指令重排序优化(通过内存屏障实现)
这就解决了多线程环境下“脏读”问题,即一个线程修改了共享变量,另一个线程能立即看到变化。
立即学习“Java免费学习笔记(深入)”;
如何使用volatile关键字
使用方式很简单,只需在变量声明前加上volatile修饰符:
private volatile boolean running = true;
常见应用场景是控制线程运行状态:
public class Worker {
private volatile boolean running = true;
public void run() {
while (running) {
// 执行任务
}
System.out.println("线程结束");
}
public void stop() {
running = false; // 其他线程调用stop()后,run()中的循环能立即感知
}
}
如果没有volatile,主线程修改了running为false,Worker线程可能还在用自己的工作内存中的true值,导致无法及时停止。
volatile不保证原子性
注意:volatile不能替代synchronized或Atomic类。它只保证可见性和有序性,不保证复合操作的原子性。
例如下面的操作不是原子的:
volatile int count = 0;count++ 实际包含读、加、写三步。多个线程同时执行时,仍可能出现竞态条件。
正确做法是使用AtomicInteger或加锁:
private AtomicInteger count = new AtomicInteger(0);
// 或者
synchronized void increment() {
count++;
}
适用场景总结
volatile适用于以下情况:
- 作为线程间的标志位(如shutdown、initialized)
- 单次读写操作本身就是原子的(如boolean、int赋值)
- 需要禁止指令重排序,比如双重检查的单例模式
基本上就这些。volatile是一个简单但容易误用的关键字,理解它的作用边界很重要:它解决的是可见性问题,不是并发安全的万能药。











