Volatile

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

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

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

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

禁止指令重排序

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

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

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

原理:读前写后加屏障

6a682433e913819c24ccc5b887fa4a7b437fc521

729fc1f3398beba9fa6ad2e201a8ec9c16feefe9

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

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

5dd16a44699042711635ffcb38156e3fa869ef49

0268a339340b567cad139512f4b72a758287de5f

DCL问题:

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
<p>class Singleton {</p>
<p>private volatile static Singleton instance; // 必须是 volatile</p>
<p>public static Singleton getInstance() {</p>
<p>if (instance == null) { // (A) 第一次检查</p>
<p>synchronized (Singleton.class) {</p>
<p>if (instance == null) { // (B) 第二次检查</p>
<p>instance = new Singleton(); // (C) 问题所在</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>return instance;</p>
<p>}</p>
<p>}</p>

85fbc626d31015120dac5c8b4cda51302d54f5db

synchronized不会让重排序失效

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

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