Volatile

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

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

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

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

禁止指令重排序

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

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

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

原理:读前写后加屏障

6a682433e913819c24ccc5b887fa4a7b437fc521

729fc1f3398beba9fa6ad2e201a8ec9c16feefe9

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

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

5dd16a44699042711635ffcb38156e3fa869ef49

0268a339340b567cad139512f4b72a758287de5f

DCL问题:

Code:

```java

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;

}

}

```

85fbc626d31015120dac5c8b4cda51302d54f5db

synchronized不会让重排序失效

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

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