1.禁止指令重排序
创建对象要经过如下几个步骤
a. 分配内存空间
b. 调用构造器,初始化实例
c. 返回地址给引用
但是JVM具有指令重排的特性,执行的顺序有可能变成 a-c-b,指令重排在单线程下不会出现问题,但是在多线程下会导致一个线程获得还没有初始化的实例。例如:线程T1执行了a,b,此时线程T2调用getInstance()方法发现INSTANCE不为null,因此返回INSTANCE,但此时INSTANCE还未被初始化。
2.保证可见性
由于可见性问题,线程T1在自己的工作线程内创建了实例,但此时还未同步到主内存中,此时线程T2判断INSTANCE还是null,那么线程T2又将在自己的工作线程创建一个实例,这样就创建了多个实例
如果加上了volatile修饰INSTANCE之后,保证了可见性,一旦线程T1返回了实例,线程T2可以立即发现INSTANCE不为null