zoukankan      html  css  js  c++  java
  • 单例模式中指令重排序及需要使用volatile的理解

    创建单例模型的方法有多种,我们常用的是双重校验法,代码如下:

    public class SingleTon {
        private static SingleTon instance = null;
        private SingleTon(){}
    
        public static SingleTon getInstance(){
            if(instance == null) {//第一次判断是否为null
                synchronized (SingleTon.class){//使用synchronized对class加锁
                    if(instance == null) {//再次判断是否为空
                        instance = new SingleTon();
                    }
                }
            }
            return instance;
        }
    }  

    上述代码,在执行10万、20万次可能没有问题,但是总有可能会出现一种报null的异常;分析如下:

    instance = new SingleTon();
    

    上面的代码,在底层其实是分成了3步:

    1.分配地址空间
    2.初始化SingleTon对象
    3.将SingleTon对象的地址赋值给instance,此时instance不为null
    

    我们都知道,jvm为了提高性能,编译器和处理器都会对指令进行重排序,上述的3步,中2和3是没有数据依赖,可以重排序,所以可能的执行顺序是1/3/2,所以当第一个线程在按照1/3/2创建单例时,正好执行到了3步骤,只是将地址空间赋值给instance,而没有初始化SingleTon对象,第二个线程过来以判断instance不为null,直接就调用单例内部其他方法的话可能就会报null

    总结,所以在使用双重校验创建单例时,instance需要使用volatile来修饰

      

  • 相关阅读:
    bzoj4236JOIOJI
    bzoj1002[FJOI2007]轮状病毒
    bzoj4563[Haoi2016]放棋子
    前端框架——Bootstrap
    jQuery三——筛选方法、事件
    jQuery二——属性操作、文档操作、位置属性
    jQuery基础——选择器、效果
    JavaScirpt(JS)——BOM浏览器对象模型
    JavaScirpt(JS)——DOM文档对象模型
    JavaScirpt(JS)——js介绍及ECMAScript
  • 原文地址:https://www.cnblogs.com/yayin/p/14158614.html
Copyright © 2011-2022 走看看