单例模式——双重校验锁

//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 查看字节码时并没有发现指令重排的现象(能力有限)。。

原创文章 25 获赞 16 访问量 8611

猜你喜欢

转载自blog.csdn.net/qq_39914581/article/details/89394161