在 Java 中,volatile 是可以防止特定情况下的指令重排的,但要理解“防止什么、怎么防止、范围有多大”。
volatile 和指令重排的关系volatile 的两大语义(JMM)在 Java 内存模型(JMM) 中,volatile 具有以下语义:
volatile 变量的写,对其他线程立即可见✅ 所以:volatile 确实可以防止指令重排,但不是“所有重排都不能发生”
volatile 如何防止指令重排?volatile 的底层实现依赖于 内存屏障(CPU 级别),例如:
StoreStore barrier
写 volatile 变量
StoreLoad barrier
LoadLoad barrier
读 volatile 变量
LoadStore barrier
这些屏障限制了编译器和 CPU 的重排序行为。
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() 实际分三步:
instance⚠️ 没有 volatile 时,可能发生重排:
分配内存 → 赋值 → 初始化
其他线程可能看到 instance != null,但对象还没初始化完 → 崩溃
✅ volatile 禁止这种重排
volatile 不能防止什么?volatile int count = 0;
count++; // 非原子操作
❌ 多线程 count++ 仍然有并发问题
✅ 需要用 synchronized / AtomicInteger
volatile 变量仍可重排int a = 1;
volatile boolean flag = true;
int b = 2;
flag 前后的代码 相对 flag 不会重排a = 1 和 b = 2 之间仍可能重排volatile 满足以下 happens-before 规则:
写 volatile 变量 happens-before 后续对该变量的读
这正是防止重排和保证可见性的理论依据。
Java 的
volatile可以防止与volatile变量相关的指令重排,保证可见性和有序性,但不保证原子性。
如果你愿意,我也可以:
volatile / synchronized / final免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。