1、初始化对象需要哪些步骤:A a=new A();
(1)分配内存空间
(2)执行构造方法、初始化对象
(3)把这个对象指向这个空间
2、A a=new A();未加volatile修饰,执行顺序可以是(1) (2) (3),也可以是(1) (3) (2)。
按(1) (3) (2)顺序执行,(1)先分配空间,但空间内容还是未初始化的,(3)变量指向这个空间,(2)初始化,把内容放入空间。
这样的执行顺序是会有问题的,比如:
单例模式,两个线程同时跑,第一个线程跑的快,跑到了new赋值初始化那儿,运行顺序1 3 2,此时跑到了3,变量当前已经指向了一个空间,所以判断为非空了,但还没有内部初始化,类内部还是空的。
这个时候,第2个线程判断非空就直接拿到这个单例实例了,这个实例就是一个内容未初始化,但已指向了一个空间的半成品,就有问题。
所以用volatile保证初始化过程不指令重排,按1 2 3顺序执行,就不会拿到半成品了。
原文:https://www.cnblogs.com/npng09/p/14871137.html