单例模式的双重检测

 2023-09-15 阅读 28 评论 0

摘要:单例模式是设计模式中比较常见简单的一种,典型双重检测写法如下: public class SingletonClass { private volatile static SingletonClass instance = null; public static SingletonClass getInstance() { if (instance == null) { synchronized

单例模式是设计模式中比较常见简单的一种,典型双重检测写法如下:

public class SingletonClass { private volatile static SingletonClass instance = null; public static SingletonClass getInstance() { if (instance == null) { synchronized (SingletonClass.class) { if(instance == null) { instance = new SingletonClass(); } } } return instance; } private SingletonClass() { } 
}

接下来对该写法进行分析,为何这样写?

一、为何要同步:

多线程情况下,若是A线程调用getInstance,发现instance为null,那么它会开始创建实例,如果此时CPU发生时间片切换,线程B开始执行,调用getInstance,发现instance也null(因为A并没有创建对象),然后B创建对象,然后切换到A,A因为已经检测过了,不会再检测了,A也会去创建对象,两个对象,单例失败。因此要同步。

 

请实现一个单例模式?二、同步为何不用 public synchronized static SingletonClass getInstance(),也就是说为何不同步这个方法,而要同步下面的语句:

因为synchronized修饰的同步块可是要比一般的代码段慢上几倍,如果经常调用getInstance,那么性能问题就得考虑了。

 

三、最外层为何要有if (instance == null)判断:

因为我们在分析二中,发现依旧存在着性能问题,也就是说,只要getInstance方法被调用,那么就会执行同步这个操作,于是我们加个判断,当instance没有被实例化的时候,也就是需要去实例化的时候才去同步。

 

数据混淆、四、instance为何要有volatile 修饰:

这个问题就涉及到了编译原理,所谓编译,就是把源代码“翻译”成目标代码——大多数是指机器代码——的过程。针对Java,它的目标代码不是本地机器代码,而是虚拟机代码。编译原理里面有一个很重要的内容是编译器优化。所谓编译器优化是指,在不改变原来语义的情况下,通过调整语句顺序,来让程序运行的更快。这个过程成为reorder。

JVM实现可以自由的进行编译器优化。而我们创建变量的步骤:

1、申请一块内存,调用构造方法进行初始化。

2、分配一个指针指向这块内存。

而这两个操作,JVM并没有规定谁在前谁在后,那么就存在这种情况:线程A开始创建SingletonClass的实例,此时线程B调用了getInstance()方法,首先判断instance是否为null。按照我们上面所说的内存模型,A已经把instance指向了那块内存,只是还没有调用构造方法,因此B检测到instance不为null,于是直接把instance返回了——问题出现了,尽管instance不为null,但它并没有构造完成,就像一套房子已经给了你钥匙,但你并不能住进去,因为里面还没有收拾。此时,如果B在A将instance构造完成之前就是用了这个实例,程序就会出现错误了。

双重锁单例模式。在JDK 5之后,Java使用了新的内存模型。volatile关键字有了明确的语义——在JDK1.5之前,volatile是个关键字,但是并没有明确的规定其用途——被volatile修饰的写变量不能和之前的读写代码调整,读变量不能和之后的读写代码调整!因此,只要我们简单的把instance加上volatile关键字就可以了。

 

转载请标明出处:https://www.cnblogs.com/tangZH/p/10031337.html 

参考链接:http://blog.51cto.com/devbean/203501

转载于:https://www.cnblogs.com/tangZH/p/10031337.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/63379.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息