双重检验的单例模式,为什么要用volatile关键字
双重检验的单例模式是比较推荐的单例写法,在该代码中的单例对象的是用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关键字的更多相关文章
- 双重检查锁单例模式为什么要用volatile关键字?
前言 从Java内存模型出发,结合并发编程中的原子性.可见性.有序性三个角度分析volatile所起的作用,并从汇编角度大致说了volatile的原理,说明了该关键字的应用场景:在这补充一点,分析下v ...
- 双重检验锁模式为什么要使用volatile?
并发编程情况下有三个要点:操作的原子性.可见性.有序性. volatile保证了可见性和有序性,但是并不能保证原子性. 首先看一下DCL(双重检验锁)的实现: public class Singlet ...
- 由单例模式学到:volatile关键字
MSDN上说: volatile 关键字指示一个字段可以由多个同时执行的线程修改. 声明为 volatile 的字段不受编译器优化的限制. 这样可以确保该字段在任何时间呈现的都是最新的值. volat ...
- 对Java单例模式 volatile关键字作用的理解
单例模式是程序设计中经常用到的,简单便捷的设计模式,也是很多程序猿对设计模式入门的第一节课.其中最经典的一种写法是: class Singleton { private volatile static ...
- Java 中 volatile 关键字及其作用
引言 作为 Java 初学者,几乎从未使用过 volatile 关键字.但是,在面试过程中,volatile 关键字以及其作用还是经常被面试官问及.这里给各位童靴讲解一下 volatile 关键字的作 ...
- 单例模式双重检验锁的判断是否为null的意义
关于双重检验锁首先简单来看一个小例子: public class Singleton{ private static Singleton instance = null; private Single ...
- 从简单示例看对象的创建过程, 为什么双重检查的单例模式,分析Volatile关键字不能少
编译指令 :javac Test.java 反编译指令: javap -v Test 代码 public class ObjectTest { int m = 8; public static voi ...
- java多线程(三):多线程单例模式,双重检查,volatile关键字
一.事先准备 首先准备一个运行用的代码: public class Singleton { public static void main(String[] args) { Thread[] thre ...
- Java单例模式和volatile关键字
单例模式是最简单的设计模式,实现也非常"简单".一直以为我写没有问题,直到被 Coverity 打脸. 1. 暴露问题 前段时间,有段代码被 Coverity 警告了,简化一下代码 ...
随机推荐
- Linux查看GPU使用情况
watch -n 10 nvidia-smi 一.watch watch命令用来定时执行某个程序 二.nvidia-smi nvdia-smi是英伟达自带的GPU监控命令.
- Octave及其工具包的安装
Octave的安装: http://blog.sina.com.cn/s/blog_1358485f70102wmpa.html http://www.gnu.org/software/octave/ ...
- Rplidar学习(一)—— 开发套件初识
一.简介 RPLIDAR A1 开发套装包含了方便用户对 RPLIDAR A1 进行性能评估和早期开发所需的配套工具. 用户只需要将 RPLIDAR A1 模组与 PC 机连接,即可在配套的评估软件中 ...
- apktool 在mac下的使用 -反编译安卓apk文件
1.下载apktool 点击这里下载 ,里面有两个文件,一个是.jar,一个是自己写的脚本.sh 注:最新的apktool.jar 文件可以点击这里下载 .sh脚本是自写脚本可不用更新最新,下载的ja ...
- ORACLE在线切换undo表空间
切换undo的一些步骤和基本原则 原文:http://www.xifenfei.com/3367.html 查看原undo相关参数 SHOW PARAMETER UNDO; 创建新undo空间 cre ...
- ADF_Starting系列3_使用ADF开发富Web应用程序之开发User Interface
内容中包含 base64string 图片造成字符过多,拒绝显示
- 【转】Scheme 编程环境的设置
Scheme 编程环境的设置 介绍了这么久的 Scheme,却没有讲过如何配置一个高效的 Scheme 的编程环境.有些人开始学习 Scheme 的时候感觉无从下手,所以今天讲一下它的配置. Sche ...
- C++ 虚函数表浅析
一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数. 纯虚函数(Pure Virtual Functi ...
- Oracle中文乱码解决办法总结
AMERICAN_AMERICA.WE8ISO8859P1,这个字符编码是西欧字符编码,对应于.Net的就是iso-8859-1字符编码,所以只需要改到系统的默认字符编码就行了. 解决方法: (1) ...
- Shell脚本:向磁盘中批量写入数据
一.关于本文 工作要做的监控系统需要监控磁盘空间的使用率并报警.在测试这个功能的时候需要模拟两个场景:一是磁盘空间不断增长超过设定的阈值时,需要触发报警机制:二是磁盘空间降落到低于报警阈值的时候,不再 ...