我大概了解你的疑惑点,上面的评论其实已经可以解决你的疑惑了。 `另外一个线程访问到的 singleton 如果不为 null 的话就肯定实例化了吗` 问题的关键在于,Sychronized加锁的位置,它没有对getSingleton()整个方法解锁,而是判断singleton为null后才会去抢锁,所以多个线程可以同时进入getSingleton方法。 由于`synchronized` 的有序性是持有相同锁的两个同步块只能串行的进入,即被加锁的内容要按照顺序被多个线程执行,**但是其内部的同步代码还是会发生重排序** ,使块与块之间有序可见。 那么如果不加上volatile防止指令的重排序,new Singleton() 方法被拆成了三个操作,并且经过重排序之后的顺序是这样的话: 1. 分配内存 2. 将实例引用赋值给 singleton 变量 3. 实例初始化 其中线程A假设在sychronized块中将内存地址赋值给了对象,`其他线程此时调用getSingleton()`,发现singleton此时不为空了,那么直接返回singleton,但是此时singleton`还未完成初始化`,那么问题就出现了。