volatile 关键字
volatile 是轻量级的同步机制,用于保证变量的可见性和有序性。
核心特性
可见性
当一个线程修改 volatile 变量,其他线程立即看到最新值:
Java
private volatile boolean running = true;
public void stop() {
running = false; // 立即可见
}
public void work() {
while (running) { // 读取最新值
// 工作逻辑
}
}
禁止指令重排序
volatile 变量的读写操作不会被重排序,保证有序性。
不保证原子性
volatile 不能保证复合操作的原子性:
Java
private volatile int count = 0;
// 错误:不保证原子性
public void increment() {
count++; // 读-改-写三步,非原子
}
适用场景
| 场景 | 是否适合 volatile | 说明 |
|---|---|---|
| 状态标志位 | ✅ 适合 | 单线程写,多线程读 |
| 单例双重检查锁 | ✅ 适合 | 防止对象初始化重排 |
| 计数器 | ❌ 不适合 | 需要原子性,用 Atomic |
| 依赖当前值 | ❌ 不适合 | count++ 等复合操作 |
双重检查锁单例示例
Java
public class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查
instance = new Singleton();
}
}
}
return instance;
}
}
volatile 作用:防止
new Singleton()的 1-分配内存、2-初始化、3-赋引用 被重排为 1-3-2,避免返回未初始化对象。
volatile vs synchronized
| 特性 | volatile | synchronized |
|---|---|---|
| 可见性 | ✅ 保证 | ✅ 保证 |
| 原子性 | ❌ 不保证 | ✅ 保证 |
| 有序性 | ✅ 禁止重排 | ✅ 保证 |
| 性能 | 高(无锁) | 有锁开销 |
| 适用场景 | 状态标志、单例 | 一般同步 |
要点总结
- volatile 保证可见性:修改立即对其他线程可见
- volatile 禁止指令重排序:保证有序性
- volatile 不保证原子性:复合操作需用 Atomic 或 synchronized
- 适用场景:状态标志位、单例双重检查锁
- 不适用场景:计数器、依赖当前值的操作
- 性能比 synchronized 高,但功能受限
📝 发现内容有误?点击此处直接编辑