博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于DCL双重锁失效及解决方案
阅读量:7022 次
发布时间:2019-06-28

本文共 1197 字,大约阅读时间需要 3 分钟。

hot3.png

关于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://my.oschina.net/u/3318187/blog/1860909

你可能感兴趣的文章
nginx 配置手机端PC端访问不同的项目
查看>>
SpriteKit-(SKNode)
查看>>
并发编程可能存在的问题
查看>>
c++ 不太懂得地方
查看>>
前端面试问题整理 第一部分
查看>>
挖一口自己的井
查看>>
[Dart] Flutter 上传文件
查看>>
XML概述
查看>>
leetcode-598-Range Addition II
查看>>
springboot + shiro 验证码与记住登录
查看>>
小猿圈分享HTML5中form如何关闭自动完成功能的方法
查看>>
Carthage 安装与使用
查看>>
详解 Cookie,Session,Token
查看>>
jq 登录正则验证
查看>>
TCP之三次握手和四次挥手
查看>>
【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
查看>>
phpcms v9 评论的bug.
查看>>
使用Jmeter进行APP接口测试经验总结
查看>>
微信智能硬件应用——微信插座控制
查看>>
有关public接口和友元类的讨论
查看>>