个人理解,你的回答是对的。先跑A线程,因为new 对象的过程不是原子的,那就可能分配了内存但没有初始化,此时跑B线程,check时因为对象分配了内存不会为null,直接返回了一个没有初始化完成的对象,然后A线程再初始完对象……所以根源在于 new 操作非原子,存在被指令重排的可能性,对象虽然只会被 new 一次而且可以成功初始化,但在 new 的过程中,其他线程可能会拿到未被初始化完成的对象。