双重检验的单例模式,为什么要用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 警告了,简化一下代码 ...
随机推荐
- Spring MVC 教程,快速入门,深入分析[1-11]
资源下载: Spring_MVC_教程_快速入门_深入分析V1.1.pdf SpringMVC核心配置文件示例.rar 作者:赵磊 博客:http://elf8848.iteye.com ...
- grep 和 awk的buffer
当使用 tail -f test.log | grep "mode" | awk '{print $5}'命令 或者 tail -f test.log | awk '/mode/ ...
- Swift中的Any 与 AnyObject、AnyClass的区别?
在 Swift 中能够表示 “任意” 这个概念的除了Any .AnyObject以外,还有一个AnyClass. Any.AnyObject.AnyClass有什么区别: AnyObject是一个成员 ...
- maven常见问题问答(转)
转自:http://www.oschina.net/question/158170_29368 1.前言 Maven,发音是[`meivin],"专家"的 意思.它是一个很好的项目 ...
- 基于 CADisplayLink 的 FPS 指示器详解
前言 之前在开发中有使用到计时器NSTimer,后来了解到iOS中不同的计时方法,其中就包括了CADisplayLink.基于CADisplayLink以屏幕刷新频率同步绘图的特性,尝试根据这点去实现 ...
- Virtualbox虚拟机克隆
Vmware Workstation可以提供虚拟机的克隆,可以安装好虚拟机之后可以非常方便的复制一个虚拟机,这样在搭建多台虚拟机的环境下非常方便,无需一台台的安装系统,但是Virtualbox在图形界 ...
- mysql 1449 : The user specified as a definer ('root'@'%') does not exist
1)创建试图时抛出此错误信息,如下图所示: 2)从网上搜索了一下,是SQL权限问题,通过如下的方式便可以解决: 3)再次执行创建视图的语句,验证一下问题是否已经解决,可以了,如下所示: 4)参考如下所 ...
- 【struts2】预定义拦截器
1)预定义拦截器 Struts2有默认的拦截器配置,也就是说,虽然我们没有主动去配置任何关于拦截器的东西,但是Struts2会使用默认引用的拦截器.由于Struts2的默认拦截器声明和引用都在这个St ...
- RSA加密异常
在利用RSA进行数据加密时,出现如下异常: Exception bytes at com.sun.crypto.provider.RSACipher.a(DashoA13*..) at com.sun ...
- C++转型操作符
转:http://www.cnblogs.com/hazir/archive/2012/04/14/2447251.html 旧式的C转型方式,几乎允许你将任何类型转换为任何其它类型,有其自身的缺陷, ...