Volatile
| Preknowledge | ![]() |
|---|
| 规则 | 修饰成员变量 和 静态成员变量,不能修饰局部变量 |
|---|---|
| 必须写进主内存 | volatile 会让线程在写变量时立即把新值刷新到主内存, 也会让线程在读变量时强制从主内存读取最新值。 避免线程在自己的工作内存中找变量 |
| 禁止指令重排序 | 在 volatile 变量的读写前后,JVM 会插入内存屏障, 防止编译器和CPU进行乱序优化。 确保了cpu按照我们字节码指令来执行 |
原理:读前写后加屏障
|
volitail可以禁止读屏障之后的命令跑到前面去, 写屏障之前的跑到后面去,禁止指令冲排序 |
|---|---|
图
|
|
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; } } |
synchronized不会让重排序失效 但是由于代码块中是单个线程执行 所以即使重排序了结果也是正确的 |
|---|---|
| 解决方法 | volatile来确保 instance=new Instance()不重排指令 |





