为啥说java双重检查(double-check)可能会失效

不用在纠结这个了,现在一般用enum或者静态内部类来实现单例。

■网友
前提实在jdk1.5之前会失效。jdk1.5之后,instance如果被声明成volatile的成员:
private static volatile Singleton instance = null; 则不会出现题主所说的“失效”性问题。这是因为jdk1.5之后的版本都增强了JMM的实现。由于计算机体系结构的发展,老的JMM不能满足当前硬件尤其是CPU体系架构的需要,JDK1.5增强了内存模型的功能。在本例中,因为JMM增强了volatile的语义,禁止编译器对volatile变量的读写进行重排序。对应于JMM的偏序原则(Happens-Before原则是JMM对多线程内存可见性的规则性描述):
volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作对应题主的问题,JMM保证了线程A在3中对instance的写会先行发生于线程B在0中对instance的读。再结合单线程程序次序原则和传递性原则以及synchronized同步可见性的共同保证,确保了线程A读到的肯定是一个初始化的instance对象。

■网友
理解是对的,另一个线程运行到0处可能看到一个不完成的对象。
要修正可以参阅 多线程环境下对象的安全发布相关
出问题的原因涉及 指令重排相关
最直接的,给那个变量加上volatile修饰即可
【为啥说java双重检查(double-check)可能会失效】 有不少类似的问题,上看下别的问题下的回答就好了


    推荐阅读