public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}mem = allocate();         1    //Allocate memory for Singleton object.
singleton = mem;         2      //Note that instance is now non-null, but
                                         //has not been initialized.
ctorSingleton(singleton ); 3     //Invoke constructor for Singleton passing
                                          //instance.在 JVM 的即时编译器中存在指令重排序的优化.也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2.如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。疑问: 为什么使用了synchronized同步还会被其他线程抢占?