文档章节

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

DannyCoder
 DannyCoder
发布于 07/22 14:20
字数 857
阅读 9
收藏 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
博文 43
码字总数 18830
作品 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
从Java内存模型角度理解安全初始化

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

登高且赋
2017/10/13
0
0
说一说你对DCL双检查锁的了解?

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

nj-zhangmq
2016/12/09
15
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Confluence 6 删除垃圾内容

属性(profile)垃圾 属性垃圾的定义为,一个垃圾用户在 Confluence 创建了用户,但是这个用户在自己的属性页面中添加了垃圾 URL。 如果你有很多垃圾用户在你的系统中创建了属性,你可以使用...

honeymose
今天
0
0
qduoj~前端~二次开发~打包docker镜像并上传到阿里云容器镜像仓库

上一篇文章https://my.oschina.net/finchxu/blog/1930017记录了怎么在本地修改前端,现在我要把我的修改添加到部署到本地的前端的docker容器中,然后打包这个容器成为一个本地镜像,然后把这...

虚拟世界的懒猫
今天
1
0
UML中 的各种符号含义

Class Notation A class notation consists of three parts: Class Name The name of the class appears in the first partition. Class Attributes Attributes are shown in the second par......

hutaishi
今天
1
0
20180818 上课截图

小丑鱼00
今天
1
0
Springsecurity之SecurityContextHolderStrategy

注:下面分析的版本是spring-security-4.2.x,源码的github地址是: https://github.com/spring-projects/spring-security/tree/4.2.x 先上一张图: 图1 SecurityContextHolderStrategy的三个......

汉斯-冯-拉特
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部