`
逆风的香1314
  • 浏览: 1453366 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于单例(Singleton)模式实现方式的反思

阅读更多
    大家都知道单例模式,也知道实现的方法,最近看到几个网友推荐的文章,仔细思考了一下,发现我以前的想法是有问题的。

    先看我一直使用的单例代码样例:
  1. /**
  2.  * 一段我一直使用的单例实现的代码。
  3.  * 
  4.  * @author 赵学庆,Java世纪网(java2000.net)
  5.  * 
  6.  */
  7. public class Singleton {
  8.   private static volatile Singleton instance;
  9.   private Singleton() {
  10.   }
  11.   public static Singleton getInstance() {
  12.     if (instance == null) { // 1
  13.       synchronized (Singleton.class) { // 2
  14.         if (instance == null// 3
  15.           instance = new Singleton(); // 4
  16.       }
  17.     }
  18.     return instance;
  19.   }
  20. }

系统先判断是否已经初始化(1),
如果没有初始化则进入同步(2),
然后再次判断是否已经初始化(3),
如果还是没有则初始化一个(4).

    系统考虑了多CPU问题,使用了 volatile 这个修饰符。 我自认这个代码没有任何问题,但是:??

    一个文章里说到的奇怪的执行顺序引起了我的注意,我来说明一下2个线程的执行过程:

    线程1这行到了(4),此时系统需要做的事情是给Singleton分配内容,然后进行初始化,可是对instance的赋值操作是在类初始化之前完成的。那没就会出现

    线程2 此时拿到了CPU,此时判断instance 已经不再是null,于是他使用了这个已经分配了内存,但没有初始化完毕的类,然后造成运行结果异常。

    这个问题我想还是很有可能的,毕竟我们无法保证JVM一定在类已经完全初始化完毕之后再赋值给instance。因为这样做,系统要额外分配一个变量用来临时指向新分配的内存,完成所有的初始化之后再把内存指向instance。而正常的理解,肯定是不会额外的浪费这个变量的(希望我的猜测是错的,我宁可我是错的)。


下面是我再次搜索并整理的更安全的初始化方法,大家参考看看:

第一种,使用静态初始化
  1. class Singleton {
  2.   private static volatile Singleton instance = new Singleton();
  3.   private Singleton() {
  4.   }
  5.   public static Singleton getInstance() {
  6.     return instance;
  7.   }
  8. }
第二种,使用
静态内部类进行初始化
  1. class Singleton {

  2.   static class SingletonHolder {
  3.     static volatile Singleton instance = new Singleton();
  4.   }
  5.   private Singleton() {
      }

  6.   public static Singleton getInstance() {
  7.     return SingletonHolder.instance;
  8.   }

  9. }
    有评价说,第二种更加的安全。我能力有限,实在不能窥透他们的区别,我只能按照保守的估算,在我以后的代码里,全部用第二种方法。

    另外,楼下网友提供的用临时变量的方法,你可以参考我的参考文章,里面讲述了理由。在一些编译器优化时,会把它优化掉,造成并不能达到我们要的结果。也就是编译器会认为你的那个临时变量是多余的。

    期待牛人能给个更准确的说法。


参考文章:
1 解析 Java 类和对象的初始化过程

2 Java中的模式 --单态
3 The "Double-Checked Locking is Broken" Declaration


分享到:
评论

相关推荐

    吉大软件设计模式ppt、示例代码及平时作业

    创建型模式关注对象的创建,如单例模式(Singleton)、工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory)。它们旨在提供一种创建对象的最佳方式,同时降低代码之间的耦合度。 结构型模式涉及如何...

    GoF 23种设计模式解析附C++实现源码(2nd Edition

    - **1.3 Singleton模式**:单例模式确保一个类只有一个实例,并提供一个全局访问点。这对于控制对资源的访问特别有用,例如数据库连接。 - **1.4 Builder模式**:构建者模式将一个复杂对象的构建与其表示分离,使得...

    C#设计模式作业1、3.rar

    在C#中,动态代理(如System.Reflection.Emit命名空间中的动态类型生成)和接口代理(通过实现相同接口的方式)是常见的实现方式,常用于权限控制、性能优化和远程调用等场景。 6. 装饰器模式(Decorator Pattern)...

    关于23种设计模式的有趣见解

    创建型模式关注对象的创建,如单例模式(Singleton)、工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory)。它们帮助我们在不指定具体类的情况下创建对象,使代码更具灵活性。 结构型模式涉及如何...

    《Java设计模式》课后答案-刘伟.rar

    创建型设计模式如单例(Singleton)、工厂方法(Factory Method)、抽象工厂(Abstract Factory)、建造者(Builder)和原型(Prototype),它们主要关注对象的创建过程,使得代码更加灵活且易于扩展。 结构型设计...

    设计模式C++版

    3. Singleton模式,单例模式,确保一个类只有一个实例,并提供全局访问点。 4. Builder模式,建造者模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 5. Prototype模式,原型模式...

    主流设计模式用例(均可单独调试)Java编写

    1. **创建型模式**:这类模式主要关注对象的创建过程,包括单例模式(Singleton)、工厂模式(Factory)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)和原型模式(Prototype)。例如,单例模式确保一...

    南华大学软件设计模式作业

    首先,实验一关注的是创建型设计模式,如单例(Singleton)、工厂方法(Factory Method)和抽象工厂(Abstract Factory)。这些模式允许程序在不指定具体类的情况下创建对象,增加了代码的灵活性和可维护性。例如,...

    尚硅谷Java设计模式(图解+框架源码剖析).zip

    创建型模式关注对象的创建,如单例模式(Singleton)、工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory)等,它们提供了一种创建对象的最佳方式,使得代码更具扩展性和灵活性。结构型模式涉及到...

    23种设计模式(C++).pdf

    Singleton模式(单例模式):确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。 Builder模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 Prototype模式(原型模式...

    设计模式精解-GoF 23种设计模式解析.pdf

    - **1.3 Singleton模式**:单例模式确保一个类只有一个实例,并提供一个全局访问点。这对于控制资源访问、数据库连接等方面非常有用。 - **1.4 Builder模式**:构建者模式允许你逐步构造一个复杂的对象。该模式...

    C#设计模式 及代码

    创建型模式关注对象的创建,如单例模式(Singleton)、工厂模式(Factory Method)和抽象工厂模式(Abstract Factory)。结构型模式则关注如何组合现有的类和对象,比如适配器模式(Adapter)、装饰器模式...

    软件架构建模设计模式

    创建型模式涉及到对象的创建,如单例(Singleton)、工厂方法(Factory Method)和建造者(Builder)模式。结构型模式关注对象的组合和封装,如适配器(Adapter)、装饰器(Decorator)和代理(Proxy)模式。行为型...

    C#语言讲解的设计模式好书

    3. **创建型模式**:如单例模式(Singleton)、工厂模式(Factory Method)和抽象工厂模式(Abstract Factory),这些模式主要处理对象的创建,提供灵活的实例化过程。 4. **结构型模式**:如适配器模式(Adapter)...

    设计模式迷你手册

    创建型模式关注对象的创建过程,如单例模式(Singleton)、工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory),它们提供了一种灵活且易于管理的方式来创建对象,避免了直接new操作带来的紧耦合问题...

    design-pattern-Java设计模式

    在多线程环境中,单例模式需要考虑线程安全,常见的实现方式有懒汉式和饿汉式。 2. **工厂方法模式**:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 3. **抽象...

    JAVA设计模式

    4. **反思和改进**:对应用的设计模式进行反思,看是否真正解决了问题,是否有更好的实现方式。 **CHM文件的使用**: CHM是Microsoft编译的帮助文件格式,包含了索引、目录和HTML页面。打开`JAVA设计模式.chm`文件...

    面向对象技术之设计模式

    1. 创建型模式:这类模式主要关注对象的创建过程,如单例模式(Singleton)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)和建造者模式(Builder)。它们旨在将对象的实例化过程封装起来,...

    head first设计模式学习代码

    首先,我们来看"DesignPattern"这个目录,它可能包含了23种常见的设计模式示例代码,如单例模式、工厂模式、抽象工厂模式、建造者模式、装饰器模式、适配器模式、桥接模式、组合模式、享元模式、代理模式、命令模式...

    51CTO下载-C++设计模式.pdf

    - **Singleton模式**:确保一个类只有一个实例,并提供一个访问它的全局访问点。 - 实现:通常采用私有构造函数和静态成员函数来控制单例对象的创建。 - **Builder模式**:将一个复杂对象的构建与其表示分离,使得...

Global site tag (gtag.js) - Google Analytics