前言
在 Java 中,volatile 关键字可以保证变量的可见性,如果将变量声明为 volatile ,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。
一、volatile 关键字
volatile 关键字其实并非是 Java 语言特有的,在 C 语言里也有,它最原始的意义就是禁用 CPU 缓存。如果我们将一个变量使用 volatile 修饰,这就指示 编译器,这个变量是共享且不稳定的,每次使用它都到主存中进行读取
JMM(Java 内存模型)强制在主存中进行读取
volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。
二、禁止指令重排序
在 Java 中,volatile 关键字除了可以保证变量的可见性,还有一个重要的作用就是防止 JVM 的指令重排序。 如果我们将变量声明为 volatile ,在对这个变量进行读写操作的时候,会通过插入特定的 内存屏障 的方式来禁止指令重排序。
在 Java 中,Unsafe 类提供了三个开箱即用的内存屏障相关的方法,屏蔽了操作系统底层的差异:
public native void loadFence();
public native void storeFence();
public native void fullFence();
理论上来说,这个三个方法也可以实现和volatile禁止重排序一样的效果,只是会麻烦一些。
二、双重检验锁方式实现单例模式
双重校验锁实现对象单例(线程安全):
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton()