`
WKsandy
  • 浏览: 149190 次
  • 性别: Icon_minigender_1
  • 来自: 常州
社区版块
存档分类
最新评论

singleton模式四种线程安全的实现

阅读更多

1.描述:

    Singleton(单例)是设计模式的一种,为了保证一个类仅有一个实例,并提供一个访问它的全局访问点。

 

2.主要特点:     

    1)单例类确保自己只有一个实例(构造函数私有:不被外部实例化,也不被继承)。

    2)单例类必须自己创建自己的实例。

    3)单例类必须为其他对象提供唯一的实例。

 

3.单例模式的应用:

    资源管理器,回收站,打印机资源,线程池,缓存,配置信息类,管理类,控制类,门面类,代理类通常被设计为单例类

    如果程序有多个类加载器又同时使用单例模式就有可能多个单例并存就要找相应解决方法了

 

4.实现方法:

如果应用程序总是创建并使用单例实例或在创建和运行时开销不太

    1).Eager initialization 饿汉式单例类(依赖jvm在加载类时创建唯一单例实例)

 

public class EagerSingleton {
        // jvm保证在任何线程访问uniqueInstance静态变量之前一定先创建了此实例
        private static EagerSingleton uniqueInstance = new EagerSingleton();

        // 私有的默认构造子,保证外界无法直接实例化
        private EagerSingleton() {
        }

        // 提供全局访问点获取唯一的实例
        public static EagerSingleton getInstance() {
                return uniqueInstance;
        }
}

  

 

 如果开销比较大,希望用到时才创建就要考虑延迟实例化,或者Singleton的初始化需要某些外部资源(比如网络或存储设备),就要用后面的方法了

    2)Lazy initialization 懒汉式单例类

public class LazySingleton {
        private static LazySingleton uniqueInstance;

        private LazySingleton() {
        }

        public static synchronized LazySingleton getInstance() {
                if (uniqueInstance == null)
                        uniqueInstance = new LazySingleton();
                return uniqueInstance;
        }
}

 

 

同步一个方法可能造成程序执行效率下降100倍,完全没有必要每次调用getInstance都加锁,事实上我们只想保证一次初始化成功,其余的快速返回而已,如果在getInstance频繁使用的地方就要考虑重新优化了

 

    3)"双检锁"(Double-Checked Lock)尽量将"加锁"推迟,只在需要时"加锁"(仅适用于java 5.0 以上版本,volatile保证原子操作) 
      happens-before:"什么什么一定在什么什么之前运行",也就是保证顺序性.
      现在的CPU有乱序执行的能力(也就是指令会乱序或并行运行,可以不按我们写代码的顺序执行内存的存取过程),并且多个CPU之间的缓存也不保证实时同步,只有上面的happens-before所规定的情况下才保证顺序性.

      JVM能够根据CPU的特性(CPU的多级缓存系统、多核处理器等)适当的重新排序机器指令,使机器指令更符合CPU的执行特点,最大限度的发挥机器的性能.

      如果没有volatile修饰符则可能出现一个线程t1的B操作和另一线程t2的C操作之间对instance的读写没有happens-before,可能会造成的现象是t1的B操作还没有完全构造成功,但t2的C已经看到instance为非空,这样t2就直接返回了未完全构造的instance的引用,t2想对instance进行操作就会出问题.

    volatile 的功能:
      1. 避免编译器将变量缓存在寄存器里 
      2. 避免编译器调整代码执行的顺序

优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份

public class DoubleCheckedLockingSingleton {
        // java中使用双重检查锁定机制,由于Java编译器和JIT的优化的原因系统无法保证我们期望的执行次序。
        // 在java5.0修改了内存模型,使用volatile声明的变量可以强制屏蔽编译器和JIT的优化工作
        private volatile static DoubleCheckedLockingSingleton uniqueInstance;

        private DoubleCheckedLockingSingleton() {
        }

        public static DoubleCheckedLockingSingleton getInstance() {
                if (uniqueInstance == null) {
                        synchronized (DoubleCheckedLockingSingleton.class) {
                                if (uniqueInstance == null) {
                                        uniqueInstance = new DoubleCheckedLockingSingleton();
                                }
                        }
                }
                return uniqueInstance;
        }
}

 

    4)Lazy initialization holder class 满足所有 Double-Checked Locking 满足的条件,并且没有显示的同步操作

public class LazyInitHolderSingleton {
        private LazyInitHolderSingleton() {
        }

        private static class SingletonHolder {
                private static final LazyInitHolderSingleton INSTANCE = new LazyInitHolderSingleton();
        }

        public static LazyInitHolderSingleton getInstance() {
                return SingletonHolder.INSTANCE;
        }
}

 

分享到:
评论

相关推荐

    Java线程安全的Singleton模式:深入分析与实现

    线程安全的Singleton模式对于多线程环境尤为重要,因为它可以防止多个线程同时创建多个实例。本文将详细介绍如何在Java中创建线程安全的Singleton,包括几种常见的实现方式和最佳实践。 在Java中创建线程安全的...

    C++完美实现Singleton模式

    ### C++中实现Singleton...在C++中实现Singleton模式时,需要注意的关键点包括但不限于资源管理、线程安全以及如何有效地减少重复代码。正确应用这些技术可以使Singleton模式更加健壮和高效,从而提高整体代码的质量。

    C++ 实现的singleton 模式

    Singleton模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下都非常有用,例如管理共享资源,如数据库连接池,或者确保某个对象在整个系统中的唯一性。下面我们...

    使用C++11实现线程安全的单例模式

    线程安全的单例模式在多线程环境下尤其重要,因为不正确的实现可能导致多个线程创建多个实例,这违反了单例模式的基本原则。C++11引入了新的特性,如std::mutex和std::call_once,使得实现线程安全的单例模式变得...

    Singleton模式源程序

    2. 双重检查锁定(Double-Checked Locking):这是最常见的一种线程安全实现方式。在获取实例时先检查实例是否已经存在,若不存在再加锁并创建。这样可以减少不必要的同步开销。 3. 原子操作:利用C++11引入的std::...

    singleton设计模式java实现及对比

    在Java中,Singleton模式的实现有多种方式,每种方式都有其优缺点,我们将详细探讨这些实现方法并进行对比。 ### 1. 饿汉式(Static Final Field) 这是最简单的Singleton实现方式,通过静态初始化器在类加载时就...

    浅议单例模式之线程安全(转)

    在多线程环境下,线程安全的单例模式尤为重要,因为如果不正确实现,可能会导致多个线程同时创建多个实例,违反了单例模式的基本原则。 在Java中,单例模式通常有以下几种实现方式: 1. 饿汉式(静态常量): ...

    (创建型模式)Singleton模式

    下面我们将详细介绍Singleton模式的几种常见实现方式: 1. 饿汉式(静态常量): 在类加载时就完成了初始化,因此这种方法是线程安全的。但是,由于类加载较早,即使尚未使用Singleton,也会创建实例,造成内存...

    C++两种线程安全的单例模式的实现

    使用"懒汉模式"与"饿汉模式"实现c++的单例模式,并且确保了单例模式的第一次实例化的线程安全,以及程序结束时,单例对象的资源收回,以防内存资源的泄漏

    Java的Singleton模式代码(免资源分)

    ### Java的Singleton模式详解 #### 一、Singleton模式概述 Singleton模式是一种常用的设计模式,在Java中主要用于确保一个类只有一个...总之,理解每种实现背后的原理和机制对于合理地使用Singleton模式至关重要。

    最简单的设计模式学习Singleton模式

    2. **静态内部类**:在Java中还可以使用静态内部类的方式实现线程安全的Singleton模式,这种方式简洁且高效,无需手动加锁。 #### 五、总结 Singleton模式是一种简单而强大的设计模式,能够有效地控制类的实例数量...

    C#设计模式之Singleton模式

    还有一种更高效的线程安全实现方式是双重检查锁定(DCL): ```csharp class Singleton { private volatile static Singleton _Instance; private Singleton() { } public static Singleton Instance { get {...

    线程安全的单例模式

    综上所述,线程安全的单例模式实现是一个复杂的过程,需要综合考虑效率和线程安全两方面的因素。通过上述几种不同的实现方式,我们可以根据实际需求选择最适合的一种。其中,双重检查锁定因其较高的性能和线程安全性...

    Java常用设计模式(SingleTon、FactoryMethod、AbstractFactory)

    Java中常使用双重检查锁定(Double-Check Locking)或枚举方式来实现线程安全的单例。 ```java // 双重检查锁定示例 public class Singleton { private volatile static Singleton instance; private Singleton...

    单例模式(Singleton)的6种实现

    Java中的枚举类型是线程安全的,并且只会装载一次,设计者充分考虑到了线程安全问题,因此使用枚举实现单例模式是一种简洁而且高效的解决方案。 6. 容器式单例(Singleton Holder) 通过一个私有的静态内部类...

    C# 单例模式详解与线程安全性实现

    内容概要:本文详尽地阐述了 C# 中单例模式的设计思想以及其实现方式,并且特别针对单例模式的线例安全提供了多种解决方案,包括锁(lock),最终给出了一段非线程安全和一段线程安全版本的代码供参考。 适合人群:C# ...

    Java并行(4):线程安全前传之Singleton1

    Singleton模式在Java多线程环境中的实现需要注意线程安全问题。传统的懒汉式实现可能会导致多个实例,而使用同步方法虽然解决了安全性问题,但效率较低。双检锁(DCL)在Java 5及以上版本中提供了较好的平衡,既保证...

    深入理解线程安全与Singleton

    Singleton模式是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。然而,实现Singleton时必须考虑线程安全,尤其是在多线程环境中。传统的Singleton实现中,可能会遇到所谓的"double-check locking...

Global site tag (gtag.js) - Google Analytics