文档章节

关于DCL双重锁失效及解决方案

DannyCoder
 DannyCoder
发布于 07/22 14:20
字数 857
阅读 15
收藏 3

关于DCL双重锁失效及解决方案

 

Double  Check Lock (DCL)实现单例

DCL 方式实现单例的优点是既能够在需要时才初始化单例,又能够保证线程安全,且单例对象初始化后调用getInstance方法不进行同步锁。代码如下:

本程序的 亮点自然在getInstance方法上面,可以看到该方法对instance进行了两次判空:第一层主要是为了避免不必要的同步,第二层判断则是为了在null情况下才创建实例。这是什么意思呢?是不是有点摸不着头脑,下面就一起来分析一下。

假设线程A执行到singleton03  = new Singleton03()语句,看起来只有一行代码,但实际上它并不是原子操作,这句代码最终会被编译成多条汇编指令,它大致做了3件事:

1)给singleton03的实例分配内存。

2)调用Singleton03()构造函数,初始化成员字段。

3)将singleton03对象指向分配的内存空间(此时singleton03就不是null了)。

    但是,由于Java编译器允许处理器乱序执行,以及JDK1.5之前JMM中的Cache、寄存器到主内存回写顺序的规定,上面的2和3的顺序是无法保证的,也就是说,执行顺序可能是1-2-3也可能是1-3-2。如果是后者,并且在3执行完毕、2未执行之前,被切换到线程B上,这时候singleton03因为已经在线程A内执行过了3,singleton03已经是非空了,所以,线程B直接取走singleton03,再使用时就会出错,这就是DCL失效问题,而且这种难以跟踪难以重现的错误可能会隐藏很久。

    在JDK1.5之后,SUN官方已经注意到这种问题,调整了JVM,具体化了volatile关键字,因此,如果JDK1.5或之后的版本,只需要将singleton03的定义改成private volatile static Singleton03 singleton = null就可以保证singleton03对象每次都是从主内存中读取,就可以使用DCL的写法来完成单例模式。当然,volatile或多或少也会影响到性能,但考虑到程序的正确性,这点牺牲也是值得的。

    DCL优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高。缺点:第一次加载稍慢,也由于JMM的原因导致偶尔会失败。在高并发环境下也有一定的缺陷,虽然发送概率很小。DCL模式是使用最多的单例实现方式,它能够在需要时才实例化对象,并且能在绝大多数场景下保证对象的唯一性,除非你的代码在并发场景比较复杂或低于JDK1.6版本下使用,否则,这种方式一般能够满足要求。

以上参考《源码设计模式解析与实战》之单例模式,记以温习,若有不足,请多指教

本文转载自:https://blog.csdn.net/dgh032/article/details/80179698

共有 人打赏支持
DannyCoder
粉丝 2
博文 66
码字总数 34157
作品 0
广州
程序员
Java多线程学习(四)

单例模式 1.1立即加载/饿汉模式 立即加载既为使用类的方法的时候已经将对象创建完毕。常见的实现方法就是直接new实例化。 public class MyObject { private static MyObject myObject = new...

kakayang2011
2016/03/06
39
2
关于双重检测锁的一种无volatile实现

本文已同步到http://liumian.win/2016/12/17/dcl-without-volatile/ 上一篇博客中提到双重检测锁的无volatile实现,如何实现呢?那么在这篇博客中来一探究竟吧~ 无volatile的安全实现 先上代...

那只是一股逆流
2016/12/17
353
0
02、单例模式--SingleTon

单例模式大纲 版权声明:本文为博主原创文章,未经博主允许不得转载 PS:转载请注明出处 作者: TigerChain 地址: http://www.jianshu.com/p/62b2e89621a5 本文出自 TigerChain 简书 人人都会...

TigerChain
2017/11/04
0
0
说一说你对DCL双检查锁的了解?

DCL双检查锁是的初衷是为了解决实现单例对象的懒加载时,避免过度同步导致的性能开销,在获取单例的构造方法中通过两层if null的空校验进行双层检查,在最里面的一层校验外加了synchronized同...

nj-zhangmq
2016/12/09
15
0
从Java内存模型角度理解安全初始化

本文将简要介绍java内存模型(JMM)的底层细节以及所提供的保障,并从JMM的角度再谈如何在并发环境下正确初始化对象,这将有助于理解更高层面的并发同步机制背后的原理。 相关阅读 1.多线程安...

登高且赋
2017/10/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

初级开发-编程题

` public static void main(String[] args) { System.out.println(changeStrToUpperCase("user_name_abc")); System.out.println(changeStrToLowerCase(changeStrToUpperCase("user_name_abc......

小池仔
今天
4
0
现场看路演了!

HiBlock
昨天
14
0
Rabbit MQ基本概念介绍

RabbitMQ介绍 • RabbitMQ是一个消息中间件,是一个很好用的消息队列框架。 • ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的s...

寰宇01
昨天
9
0
官方精简版Windows10:微软自己都看不过去了

微软宣布,该公司正在寻求解决方案,以减轻企业客户的Windows 10规模。该公司声称,企业客户下载整个Windows 10文件以更新设备既费钱又费时。 微软宣布,该公司正在寻求解决方案,以减轻企业...

linux-tao
昨天
19
0
TypeScript基础入门之JSX(二)

转发 TypeScript基础入门之JSX(二) 属性类型检查 键入检查属性的第一步是确定元素属性类型。 内在元素和基于价值的元素之间略有不同。 对于内部元素,它是JSX.IntrinsicElements上的属性类型...

durban
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部