Volatile 关键字

472 阅读1分钟
  • 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();
        }
    }