查看instance = new SingletonDemo();编译后的指令,可以分为以下3步:
1)分配对象内存空间:memory = allocate();
2)初始化对象:instance(memory);
3)设置instance指向分配的内存地址:instance = memory;
由于步骤2和步骤3不存在数据依赖关系,因此可能出现执行132步骤的情况。
比如线程1执行了步骤13,还没有执行步骤2,此时instance!=null,但是对象还没有初始化完成;
如果此时线程2抢占到cpu,然后发现instance!=null,然后直接返回使用,就会发现instance为空,就会出现异常。
这就是指令重排可能导致的半初始化问题问题,因此要想保证程序100%正确就需要加volatile禁止指令重排。