Volatile

Preknowledge image1
规则 修饰成员变量 和 静态成员变量,不能修饰局部变量
必须写进主内存

volatile 会让线程在写变量时立即把新值刷新到主内存,

也会让线程在读变量时强制从主内存读取最新值

避免线程在自己的工作内存中找变量

禁止指令重排序

在 volatile 变量的读写前后,JVM 会插入内存屏障,

防止编译器和CPU进行乱序优化。

确保了cpu按照我们字节码指令来执行

原理:读前写后加屏障

image2

image3

volitail可以禁止读屏障之后的命令跑到前面去,

写屏障之前的跑到后面去,禁止指令冲排序

image4

image5

DCL问题:

Code:

class Singleton {

private volatile static Singleton instance; // 必须是 volatile

public static Singleton getInstance() {

if (instance == null) { // (A) 第一次检查

synchronized (Singleton.class) {

if (instance == null) { // (B) 第二次检查

instance = new Singleton(); // (C) 问题所在

}

}

}

return instance;

}

}

image6

synchronized不会让重排序失效

但是由于代码块中是单个线程执行 所以即使重排序了结果也是正确的

解决方法 volatile来确保 instance=new Instance()不重排指令