单例模式双重校验的再理解

提起单例模式,作为攻城狮的你我都不会感觉到陌生,而为了确保在程序中的线程安全,我们常常会倾向于双重校验和静态类两种方式。而且众所周知,在双重校验的方式中,我们发现了关键字volatile的身影,而且一直以来小编只是知道 该关键字可以保证操作之间的可见性。但是只知其一啊,今天突然明白这其中的道理:

public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
如上述代码片所示,singleton变量使用了volatile关键字修饰,也就意味着这个变量对接下来的操作具有可见性(原因稍后会有解释)。
♗ 如果上述代码中singleton变量去掉volatile关键字……

public class Singleton {
private static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
如上述代码所示,如果是单线程操作,由于代码的顺序间接的决定了执行顺序,而且在单线程中,即使jvm执行了顺序重排,仍然不会出现问题;

在讨论多线程的场景之前,我们先来科普一下 对象初始化的过程:在对象初始化也就是如第八行代码(singleton = new Singleton();  )所示,要知道,这行代码一共有三个过程:

分配对象的内存空间-->初始化对象 --> 将singleton指向刚分配好的内存地址

-----------------------------------------我是分割线-------------------------------------------

明白初始化的过程之后,我们开始讨论多线程的场景:假设现在有线程A和线程B,当两个线程同时来访问Singleton对象,但是在访问期间会有以下不安全的情况:

1)A /B 线程同时访问,这时两个线程都发现singleton为空,所以两个线程都会创建一个singleton变量,这自然不符合单例模式的初衷……

2)在不同的时间,A、B线程分别来访问这个Singleton对象,可能会出现报错的情况:

        ![image.png](https://upload-images.jianshu.io/upload_images/4587933-bb1b30c485451510.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


 如上图所示,线程B在T4时间的访问一定会出现NullPointerException,因为找不到这个对象噻!

 关于volatile修饰之后,为什么就可以避免上图中多线程访问的问题,将在下篇中讲解,敬请期待!

————————————————
版权声明:本文为CSDN博主「杨士超」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/YSC1123/article/details/77867138

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 设计模式中,最为基础与常见的就是单例模式。这也是经常在面试过程中被要求手写的设计模式。 下面就先写一个简单的单例:...
    乐百事52淑熙阅读 5,753评论 0 0
  • 定义 一个类只有一个实例,自行实例化并提供给整个系统。 基本思路 将该类构造函数私有化,并通过静态方法获取一个唯一...
    剧透下阅读 1,805评论 0 0
  • 简介 单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。许多时候整个系统只需要拥有一个的...
    上杉丶零阅读 3,619评论 0 1
  • 一、称号没想好。。。 最近几百年飞升的是一位魔法师,他没有魔法体质,却有超高的魔法天赋。 儿时接受了一点冥想术的修...
    时光勿念阅读 3,265评论 0 0
  • 一、父女第一次“吵架” 晚饭后我坐沙发上消食发呆,九九则在客厅里莫名地处于亢奋状态——自编自演,手舞足蹈。这样的“...
    山贼爷阅读 3,280评论 2 2

友情链接更多精彩内容