//new:创建一个新对象
//dup:复制之前分配对象空间的引用并压入栈顶
//invokespecail:调用实例方法(此处调用的是类的init方法)
//putstatic:将栈顶元素赋值给静态成员
public class Sington{
//volatile禁止指令重排
private static volatile Sington instance=null;
private Sington(){};
public static Sington getInstance(){
if(instance==null){
synchronized(Sington.class){
if(instance==null) {
//静态引用的赋值操作分为4个指令:new dup invokespecial putstatic
instance = new Sington();
//由于指令重排,所以这个操作有可能会是这样:new dup putstatic invokespecial
//所以如果不加volatile时存在一种情况:当对象未初始化完毕时,instace就非空了
//然后会导致其他线程获取到一个未初始化的对象
}
}
}
return instance;
}
}
最后遗憾的是我通过jclasslib 查看字节码时并没有发现指令重排的现象(能力有限)。。