双重检验的单例模式是比较推荐的单例写法,在该代码中的单例对象的是用volatile关键字修饰的。这时就产生的一个疑问,为什么需要volatile来修饰呢?
上网查看多个博客,下面简单通俗分析一下当中的原因:
贴上不加volatile单例代码

public class Singleton {
    private static Singleton s;
    private Singleton(){};
    public static Singleton getInstance() {  //1
        if(s == null) { //2
            synchronized (Singleton.class) { //3
                if(s == null) { //4
                    s = new Singleton(); //5
                }
            }
        }
        return s; //6
    }
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

以前不了解为什么需要volatile关键字,后来发现在并发情况下,如果没有volatile关键字,在第5行会出现问题
对于第5行 s = new Singleton(); //5
可以分解为3个步骤:

1 memory=allocate();// 分配内存 相当于c的malloc
2 ctorInstanc(memory) //初始化对象
3 s=memory //设置s指向刚分配的地址

上面的代码在编译器运行时,可能会出现重排序 从1-2-3 排序为1-3-2

如此在多线程下就会出现问题

例如现在有2个线程A,B

线程A在执行第5行代码时,B线程进来,而此时A执行了 1和3,没有执行2,此时B线程判断s不为null 直接返回一个未初始化的对象,就会出现问题

而用了volatile,上面的重排序就会在多线程环境中禁止,不会出现上述问题。
正确双重检验单例模式写法:

public class Singleton {
    private static volatile Singleton s;
    private Singleton(){};
    public static Singleton getInstance() {
        if(s == null) {
            synchronized (Singleton.class) {
                if(s == null) {
                    s = new Singleton();
                }
            }
        }
        return s;
    }
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

总结:加上volatile就是为了防止产生指令的重排序问题
为什么volatile能禁止指令的重排序呢?这里就涉及到volatile的原理了,这里就不多说volatile的原理,可以看看海子大神的博客:volatile关键字解析
---------------------
作者:Tuzki_小辣鸡
来源:CSDN
原文:https://blog.csdn.net/weixin_37659242/article/details/82776198
版权声明:本文为博主原创文章,转载请附上博文链接!

双重检验的单例模式,为什么要用volatile关键字的更多相关文章

  1. 双重检查锁单例模式为什么要用volatile关键字?

    前言 从Java内存模型出发,结合并发编程中的原子性.可见性.有序性三个角度分析volatile所起的作用,并从汇编角度大致说了volatile的原理,说明了该关键字的应用场景:在这补充一点,分析下v ...

  2. 双重检验锁模式为什么要使用volatile?

    并发编程情况下有三个要点:操作的原子性.可见性.有序性. volatile保证了可见性和有序性,但是并不能保证原子性. 首先看一下DCL(双重检验锁)的实现: public class Singlet ...

  3. 由单例模式学到:volatile关键字

    MSDN上说: volatile 关键字指示一个字段可以由多个同时执行的线程修改. 声明为 volatile 的字段不受编译器优化的限制. 这样可以确保该字段在任何时间呈现的都是最新的值. volat ...

  4. 对Java单例模式 volatile关键字作用的理解

    单例模式是程序设计中经常用到的,简单便捷的设计模式,也是很多程序猿对设计模式入门的第一节课.其中最经典的一种写法是: class Singleton { private volatile static ...

  5. Java 中 volatile 关键字及其作用

    引言 作为 Java 初学者,几乎从未使用过 volatile 关键字.但是,在面试过程中,volatile 关键字以及其作用还是经常被面试官问及.这里给各位童靴讲解一下 volatile 关键字的作 ...

  6. 单例模式双重检验锁的判断是否为null的意义

    关于双重检验锁首先简单来看一个小例子: public class Singleton{ private static Singleton instance = null; private Single ...

  7. 从简单示例看对象的创建过程, 为什么双重检查的单例模式,分析Volatile关键字不能少

    编译指令 :javac Test.java 反编译指令: javap -v Test 代码 public class ObjectTest { int m = 8; public static voi ...

  8. java多线程(三):多线程单例模式,双重检查,volatile关键字

    一.事先准备 首先准备一个运行用的代码: public class Singleton { public static void main(String[] args) { Thread[] thre ...

  9. Java单例模式和volatile关键字

    单例模式是最简单的设计模式,实现也非常"简单".一直以为我写没有问题,直到被 Coverity 打脸. 1. 暴露问题 前段时间,有段代码被 Coverity 警告了,简化一下代码 ...

随机推荐

  1. VMware Workstation 10.0 简中绿色精简版

    VMware Workstation是强大的虚拟机软件,能在一台机器上同时运行二个或更多Windows.DOS.LINUX系统,并进行开发.测试.部署新的应用程序.VMware10.0 延续VMwar ...

  2. 回到顶部bug

    参考自一博客(https://www.cnblogs.com/abao0/p/6642288.html)内有慕课网教程(后发现有bug, 弃置不用了) 以下有问题, 当滚动条处于顶部时, 刷新页面, ...

  3. hihocoder216周:贪心或二分

    题目链接 有N条线段,要切K刀,使得最长的线段尽量短.在最佳切割的条件下,切完之后最长的那根绳子是多长. 方法一:贪心 每次切的那一刀必然是最长的那条线段,用优先队列,每次往最长的那条线段上切一刀 方 ...

  4. 【DeepLearning】Exercise:Learning color features with Sparse Autoencoders

    Exercise:Learning color features with Sparse Autoencoders 习题链接:Exercise:Learning color features with ...

  5. log4j(三)——如何控制不同级别的日志信息的输出?

    一:测试环境与log4j(一)——为什么要使用log4j?一样,这里不再重述 二:老规矩,先来个栗子,然后再聊聊感受 import org.apache.log4j.*; //by godtrue p ...

  6. Kibana访问权限控制

    ELK平台搭建完成后,由于Kibana的服务也是暴露在外网,且默认是没有访问限制的(外部所有人都可以访问到),这明显不是我们想要的,所以我们需要利用Nginx接管所有Kibana请求,通过Nginx配 ...

  7. [转]java调用外部程序Runtime.getRuntime().exec

    Runtime.getRuntime().exec()方法主要用于执行外部的程序或命令. Runtime.getRuntime().exec共有六个重载方法: public Process exec( ...

  8. C#基础第二天-作业-九九乘法表-打印星星

    一.打印九九乘法表图形为下列效果图中的三角型的一种例: 图一效果1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 ...

  9. Vue 中组件概念

    1 为了能在模板中使用,组件必须先注册以便 Vue 能够识别.这里有两种组件的注册类型:全局注册和局部注册. 1.1 全局注册是通过Vue.component 来向Vue注册,例子 Vue.compo ...

  10. sudo: /etc/sudoers is owned by uid 755, should be 0

    在ubuntu环境下, 想往/etc/sudoers中添加可以执行sudo操作的用户,使用root将/etc/sudoers的权限修改为755后,提示出现标题中的错误: 修正方法:将/etc/sudo ...