双重检验的单例模式是比较推荐的单例写法,在该代码中的单例对象的是用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. HTTP协议详解(转)

    HTTP协议详解 转自: http://blog.csdn.net/gueter/article/details/1524447     Author :Jeffrey   My Blog:http: ...

  2. Linux 下C编程(一)文件基础

    博主原创,转载请加上http://www.cnblogs.com/jikexianfeng/p/5769357.html 一.课程概要 1.文件描述符 2.文件操作和内核数据结构 3.文件原子操作 二 ...

  3. 【javascript】js实现复制、粘贴

    使用document.ExecCommand("copy")命令,官方文档,点我. 例如: <!DOCTYPE html> <html> <head& ...

  4. 【Spring】SpringMVC之异常处理

    java中的异常分为两类,一种是运行时异常,一种是非运行时异常.在JavaSE中,运行时异常都是通过try{}catch{}捕获的,这种只能捕获显示的异常,通常项目上抛出的异常都是不可预见.那么我们能 ...

  5. IDEA 配置Gradle编译工具

    下载解压自己需要的gradle版本:https://gradle.org/releases/(免安装) 配置环境变量 打开命令窗口,输入 gradle -v IDEA配置gradle:file-> ...

  6. Oracle 12C -- temporal validity

    temporal validity需要在创建表的时候使用一个vaild-time维度(包含时间起始和结束) 创建有valid-time维度的表 (1)显式指定两个date-time列 SQL> ...

  7. 解决Mac上adb: command not found问题

    使用mac进行开发的时候,有时候需要使用adb指令来进行一些操作,但是如果没有配置过Android环境变量,可能会出现adb: command not found的问题,查了一些资料,这里记录一下ma ...

  8. C++中的成员对象

    原文链接: http://blog.csdn.net/rhzwan123/article/details/2105205 [概念] 成员对象:当一个类的成员是另一个类的对象时,这个对象就叫成员对象.概 ...

  9. Ios开发中UILocalNotification实现本地通知实现提醒功能

    这两天在做一个日程提醒功能,用到了本地通知的功能,记录相关知识如下: 1.本地通知的定义和使用: 本地通知是UILocalNotification的实例,主要有三类属性: scheduled time ...

  10. Python 文件 writelines() 方法

    概述 Python 文件 writelines() 方法用于向文件中写入一序列的字符串. 这一序列字符串可以是由迭代对象产生的,如一个字符串列表. 换行需要制定换行符 \n. 语法 writeline ...