首页 > 编程笔记 > Java笔记 阅读:23

Java volatile禁止指令重排的底层实现(新手必看)

在 Java 中,volatile 关键字确实可以禁止指令重排序,它通过内存屏障来实现这一特性。

若用 volatile 修饰共享变量,JVM 会在读取或写入 volatile 变量时插入特定类型的内存屏障,从而防止指令重排序的发生。

内存屏障是一种处理器指令,它能够影响指令的执行顺序,确保屏障前后的操作执行的有序性,这些内存屏障分为两种:
在 JMM 中,volatile 关键字的一个重要作用是防止指令重排序优化。因为编译器和处理器都可能会对指令进行重排序以优化性能和资源利用率,但这可能会破坏多线程程序的并发性质。

volatile 变量的读写操作将作为一个固定的参考点,编译器和处理器在遇到 volatile 变量时,会按照以下规则进行操作:
这些内存屏障阻止了特定类型的处理器重排序。例如,写 volatile 变量之后的读写操作不会被重排序到写入操作之前。这样,就可以创建 happens-before 关系,确保在 volatile 变量写入之后的操作不会被重排序到其之前,从而保证了线程间的内存可见性和有序性。

因此,volatile 变量的正确使用可以作为一个轻量级的同步机制,从而确保多线程程序中的共享变量访问的可见性和有序性,而无须锁的开销。然而,它并不提供复合操作的原子性(例如递增)。如果需要复杂的同步,通常还是需要使用 synchronized 关键字或 java.util.concurrent 包下的原子类。

值得注意的是,不同的处理器架构可能对内存屏障有不同的实现。例如,在 x86 架构中,读屏障和写屏障由于其较强的内存模型,往往不需要使用显式的屏障指令;而在 ARM 或其他架构中,就需要使用显式的屏障指令来保证 volatile 关键字的语义。

相关文章