- volatile 用于修饰变量, 每次读取 volatile 修饰的变量都是从主内存去去,而不是从 cpu 的缓存,每次写也是直接写入主内存。
- 禁止指定重排序
volatile 修饰的变量直接从主内存读写。
在 demo 中是一个单例模式,如果不用 volatile 修饰 single 变量,不能保证线程安全。在 TestVolatile.single = new TestVolatile(); 中会生成三条指令,(1): 初始化,(2):更新对象属性,(3):指针赋值。如果不用 volatile 修饰,线程一执行 (1)(3)(2), 当线程一执行到(3)的时候,线程二判断到 single != null 直接 return single, 但是 single 的属性并没有赋值,会产生脏数据。
public class TestVolatile {
public static volatile TestVolatile single; // 防止指令重排序
private TestVolatile() {}
public static TestVolatile getInstance() throws InterruptedException {
if(TestVolatile.single == null) {
synchronized (TestVolatile.class) {
if(TestVolatile.single == null) {
Thread.sleep(1);
TestVolatile.single = new TestVolatile(); // 使用 volatile 禁止 single 指令重排序,防止直接返回未正确初始化的 single
}
}
}
return TestVolatile.single;
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
System.out.println(TestVolatile.getInstance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}