这个其实蛮有趣的。
以文中的这个例子来讲,为避免歧义,我用abc替换了原文中的123:public class Singleton {
private static Singleton s;
private Singleton(){};
public static Singleton getInstance() { //a
if(s == null) { //b
synchronized (Singleton.class) { //c
if(s == null) { //d
s = new Singleton(); //e
}
}
}
return s; //f
}
}
线程A在执行(e)的时候可能是按照重排序后的方式进行的,即下面步骤的1-3-2:1 memory=allocate();// 分配内存 相当于c的malloc
2 ctorInstanc(memory) //初始化对象
3 s=memory //设置s指向刚分配的地址
楼主觉得由于有synchronized块的保护,所以另外一个线程B会等待A执行完(e)之后才会进入synchronized块执行(d)的判断。
而实际上,此处并发问题出在(b)这一行。即B可能在(b)处判断得到变量s不为null,从而直接跳转到(f)将一个未初始化完成的s返回。从而引发NullPointerException。