何谓双重检查成例?
来源:互联网 发布:身份证读卡器端口失败 编辑:程序博客网 时间:2024/06/10 07:49
最近在忙考试的事,笔记做的少了。
在图书馆看到了阎宏博士的《java与模式》,里面在讲单例模式时谈到了双重检查成例,以前没听过。先看下面的代码:
- public class LazySingleton{
- private static LazySingleton m_instance = null;
- private LazySingleton() {
- }
- public static LazySingleton getInstance() {
- if (m_instance == null) {
- m_instance = new LazySingleton();
- }
- return m_instance;
- }
- }
这称为赖汉式单例,初一看似乎没什么问题,但实际运用中就会发生情况。我们知道一般在J2EE环境中都是多线程的,假设当m_instance==null的瞬间,有两个线程A和B同时进入getInstance()方法内,这时就会产生两个实例。虽然最后m_instance只会引用其中的一个,但A和B已经分别获得并引用了这两个实例之一,显然这违背了单例的初衷。这时我们就会想到将getInstance()方法同步,修改后的代码如下:
- public class LazySingleton{
- private static LazySingleton m_instance = null;
- private LazySingleton() {
- }
- public static LazySingleton getInstance() {
- synchronized (LazySingleton.class) {
- if (m_instance == null) {
- m_instance = new LazySingleton();
- }
- }
- return m_instance;
- }
- }
这样就没有问题了。但还是有人会问,方法同步后会对性能造成一定影响,有没有什么办法再优化一下?
于是就有了下面这样的代码:
- public class LazySingleton{
- private static LazySingleton m_instance = null;
- private LazySingleton() {
- }
- public static LazySingleton getInstance() {
- if (m_instance == null) {
- synchronized (LazySingleton.class) {
- if (m_instance == null) {
- m_instance = new LazySingleton();
- }
- }
- }
- return m_instance;
- }
- }
这就是所谓的双重检查成例了。在同步代码外再进行一次检查,当LazySingleton已存在实例的时候,就不会进入同步代码块内,从而就解决了同步带来的性能问题。这个想法非常好,而且在C/C++里也可以用得很欢。然而不幸的是,在Java里却不行。为什么?
阎宏博士是这样解释的:在Java 编译器中,LazySingleton 类的初始化与m_instance 变量赋值的顺序不可预料。如果一个线程在没有同步化的条件下读取m_instance 引用,并调用这个对象的方法的话,可能会发现对象的初始化过程尚未完成,从而造成崩溃。
这两句话不太好理解,但“这个结论已成铁案,根本原因在于JVM的类、变量初始化机制”。java允许jvm在不影响单线程的执行语义的情况下,改变语句的执行顺序。
这里有关于双重检查成例的讨论:http://faq.csdn.net/read/184228.html
- 何谓双重检查成例?
- 单例模式的双重检查成例的研究
- 《Java与模式》学习笔记(6)——双重检查成例的研究
- 为何双重检测成例在java中不成立
- 双重检查锁定
- 双重检查加锁机制
- 双重检查锁定模式
- 双重检查锁定模式
- 双重检查锁定
- Java双重检查锁定
- 双重检查锁定
- 双重检查锁机制
- 双重检查加锁
- 广而告之-双重检查锁定模式
- 双重检查锁定失败可能性
- Double check 双重锁检查
- 双重检查锁定原理详解
- 双重检查锁定原理详解
- Random类引出的体育彩票的故事!
- 进入CSDN学习的第一天
- 开启局域网内共享的方法
- 太棒了
- 不错的地方,比CSDN主站好!
- 何谓双重检查成例?
- 在别人的失误中提炼机遇
- Windows下的修改的可用内存 (转) Tomcat内存问题 500错误
- SQL Server 2005的基本管理(1)
- 一个睡五分钟等于六个钟头的方法
- PHP面向对象-测试题(6~10)
- 或许无关于爱情
- 难,难于上青天!SOS
- 小小想法