单例的目的是为了保证运行时Singleton类只有唯一的一个实例,用于一些较大开销的操作。

饿汉式(没有线程安全问题):

由于使用static关键字进行了修饰,只能获取到一个对象,从而达到了单例,并且在Singleton类初始化的时候就创建了对象,加载到了内存。

问题:在没有使用这个对象的情况下就加载到内存是一种很大的浪费。

针对这种情况,有一种新的思想提出——延迟加载,也就是所谓的懒汉式。

懒汉式(存在线程安全问题):

这种方法在调用Singleton.getInstance()时才会创建对象,起到了延迟加载的作用。

问题:这样的写法在多个线程同时运行时,很有可能会产生多个实例对象,导致线程安全问题。

使用同步的方法解决这个问题,加上synchronized关键字,代码如下:

  使用同步的代价是会在一定程度上降低程序的并发度,并且锁定整个方法很消耗资源,原本采用延迟加载是为了节省资源,

所以,降低锁的细粒度,代码如下:

  但是这样的写法线程还是不安全,因为两个线程可以同时进入if语句,线程A实例化对象返回之后,线程B不用经过判断

能再实例化对象,并且返回另一个对象。为了解决这个问题,引入了臭名昭著的双重锁机制:

上面的代码看似解决了线程安全问题,也起到了延迟加载的作用,但是双重锁机制是没有办法工作的,有一篇文章解释的非常

深刻:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

在参考了一些资料,我认为双重锁机制之所以不能正常运行是因为,在new对象的时候,是有三个步骤的:分配内存空间,

初始化对象,然后将内存地址赋值给变量;在这么三个步骤中,极有可能会在操作上进行重排序,在重排序的情况下,还没有初始化

对象,先将内存地址赋值给了变量(这种情况是可能存在的),当线程B进入时,发现变量不为null,就会直接返回这个实例,然而此时

可能拿到的是还没有初始化完成的对象。所以双重锁机制是不提倡使用的。

在http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl文章中有提出,在新的内存模型下,实例字段使用volatile可以解

决双重锁检查的问题,因为在新的内存模型下,volatile禁止了一些重排序,但是,同时,使用volatile的性能开销也有所上升。

所以又提出一种新的模式——Initialization on Demand Holder. 这种方法使用内部类来做到延迟加载对象,在初始化这个内部类的时候,

JLS(Java Language Sepcification)会保证这个类的线程安全。代码如下:

转载于:https://www.cnblogs.com/ckgame/p/8328347.html

java单例模式之线程安全问题相关推荐

  1. 单例模式与线程安全问题浅析

    近期看到到Struts1与Struts2的比較.说Struts1的控制器是单例的,线程不安全的:Struts2的多例的,不存在线程不安全的问题.之后又想到了之前自己用过的HttpHandler... ...

  2. 单例模式及其线程安全问题

    目录 ​ 1.设计模式 2.饿汉模式 3.懒汉模式 4.线程安全与单例模式 1.设计模式 设计模式是什么? 设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案 这些解决方案是众多软件开发人 ...

  3. 单例模式与线程安全问题

    文章目录 本次的学习总结是对Java中的单例设计模式的介绍与解析,对于作为一个开发者而言这个设计模式必须要了解透彻,基本素养吧. 文章目录 文章目录 前言 一.什么是设计模式? 二.什么是单例设计模式 ...

  4. (Java多线程)线程安全问题

    文章目录 线程安全 定义 售票模拟案例 注意 线程同步 同步代码块 同步方法 Lock锁 线程安全 定义 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果 ...

  5. 浅析Java各种变量线程安全问题

    静态方法 非静态方法 静态变量 实例变量 局部变量 静态方法(Static Method) 与静态成员变量一样,属于类本身,在类装载的时候被装载到内存(Memory),不自动进行销毁,会一直存在于内存 ...

  6. 处理java多线程时线程安全问题 - ThreadLocal和Synchronized

    多线程在自动化测试中用的不多,也就是说我们用单线程可以完成大部分的自动化测试脚本. 主要有两个原因,首先是因为自动化测试首要考虑的是脚本的稳定性,所以一般会牺牲效率以保证脚本稳定,其次是由于局限于我们 ...

  7. spring单例模式与线程安全问题的解决方案

    一句话总结:1:spring容器创建对象的方式是单例的 2:spring单例模式的安全问题是使用ThreadLocal解决的 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行 ...

  8. java中SimpleDateFormat线程安全问题及解决方案

    最近看到一篇文章提到了SimpleDateFormat这个类.说这个类在单线程程序中没问题,但是在多线程环境下会线程安全的问题. 出于兴趣对这个问题进行了查证.网上有很多关于这个问题的文章,也解析了其 ...

  9. Java多线程之线程安全问题

    ⭐️前面的话⭐️ 本篇文章介绍的内容为Java多线程中的线程安全问题,此处的安全问题并不是指的像黑客入侵造成的安全问题,线程安全问题是指因多线程抢占式执行而导致程序出现bug的问题.

最新文章

  1. Linux下des对称性加密
  2. Silverlight实例_人立方
  3. 直连串口线、交叉串口线
  4. css-四种css导入方式
  5. 全球域名商解析新增量18强:万网易名位居三甲
  6. springBoot读取配置信息之Properties
  7. 阿里巴巴小程序繁星计划专题上线,汇集最优扶持资源与最新资讯!
  8. web环境下的图像打印组件
  9. 这种文件别打开, 大小不足1KB, 却可以让你电脑瘫痪
  10. win10下用ffmpeg推流拉流
  11. python roberts滤波_Python 图像处理 OpenCV (12): Roberts 算子、 Prewitt 算子、 Sobel 算子和 Laplacian 算子边缘检测技术...
  12. 小米汽车VS苹果汽车,相同赛道不同逻辑
  13. edge播放视频HTML5黑屏,edge不能播放网页视频怎么办-修复edge浏览器播放视频黑屏的方法 - 河东软件园...
  14. AB PLC 1769模拟量模块量程转换
  15. mysql common是什么_MySQL概述及入门(一)
  16. 10000电信固话如何设置呼叫转移
  17. 前端html字体设置
  18. 当Python遇到分形数学魔法 --> 树叶
  19. 自然数e这家伙怎么蹦跶出来的?
  20. Sailfish OS

热门文章

  1. java设计模式之模板模式
  2. leetcode204. 计数质数(vip题)
  3. leetcode1290. 二进制链表转整数 刷新认知,最简单算法题
  4. leetcode234 回文链表
  5. 终于,我读懂了所有Java集合——List篇
  6. 橙白oj 2017级《算法分析与设计》-练习02
  7. 三目运算符_C语言知识点:运算符的优先级和结合性
  8. www.python123.org_python爬虫-requests
  9. 在Ubuntu环境下使用vcpkg安装sqlite_orm包文件
  10. 研发团队平稳度过“从小到大”并非易事