java双检锁构造单例类的问题(jdk1.5前)

static Singleton instance = null;
    static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                if(instance == null)
                    instance = new Singleton();
            }
        }
        return instance;
    }

以上代码是典型的java双检锁构造单例模式的代码。看上去两次判空+类锁保证了多线程下的安全,其实不然,这种写法依然存在问题。
问题出现在 instance = new Singleton(); 这句话上。
这句话就是初始化一个对象,理论上这个操作的步骤大概是下面这个样子的:

  1. 分配一块内存M;
  2. 在内存M上初始化Singleton对象
  3. 将内存M的地址赋给instance。
    实际上,jvm会对这个过程进行优化,优化过后的步骤是这样的:
  4. 分配一块内存M;
  5. 将内存M的地址赋给instance;
  6. 在内存M上初始化Singleton对象。
    那么问题来了,如果有两个线程A、B都在试图获取单例,A在执行到上述步骤2的时候,发生了线程切换,此时instance是被赋予了内存的地址的,所以不为空,这时B获得时间片,开始执行逻辑,走到第一句发现instance已经不为null,直接返回了这个引用。因为这个对象还没有初始化,后续通过这个引用方位内存上的对象时,会抛出NPE。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容