`
Terry_zzz
  • 浏览: 6596 次
  • 性别: Icon_minigender_1
  • 来自: 大连
最近访客 更多访客>>
社区版块
存档分类
最新评论

单例模式与DCL

 
阅读更多

相信单例模式大家已经不陌生, 是比较常见的几种模式之一,在spring中默认的bean都是单例.


下面对该模式做下回顾与总结.


主要分为饿汉式和懒汉式, 饿汉式是在类加载时进行初始化, 懒汉式是延迟加载, 当第一次调用时,进行初始化.


单例模式需要注意的是: 


1. 要有私有构造方法, 避免外部直接实例化.

2. 要有静态的getInstance()方法.

 

3. 对于懒汉式, 要在getInstance()方法前加上同步, 避免多线程环境下出现并发问题.


单例模式基本传统实现: 
 

//饿汉式 
public class Singleton { 

  //将构造函数私有化 
  private Singleton(){ } 

  private static Singleton instance = new Singleton(); 

  public static Singleton getInstance() { 
     return instance; 
  } 
} 




//懒汉式 
public class Singleton1 { 

  private static Singleton1 instance = null; 

  //将构造函数私有化 
  private Singleton(){ } 



  public  static synchronized Singleton1 getInstance() { 
    if(instance == null){ 
     instance = new Singleton1(); 
    } 
    return instance; 
  } 
} 



 

 这个实现对于懒汉式有个问题, 就是同步了整个方法, 这样锁的粒度过大, 会影响多线程环境下的效率. 这样, 我们可以采用DCL模式进行细粒度的加锁. 如下.

 

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

 

 注意: 此种DCL模式只有在jdk1.4 之后才有效, 因为java5对内存模型作了重要的改动,其中最主要的改动就是对volatile和final语义的改变.

 

在java 5中多增加了一条happen-before规则:

  • 对volatile字段的写操作happen-before后续的对同一个字段的读操作。

利用这条规则我们可以将instance声明为volatile.

 

关于happen-before

 

我们一般说一个操作happen-before另一个操作,这到底是什么意思呢?当说操作A happen-before操作B时,我们其实是在说在发生操作B之前,操作A对内存施加的影响能够被观测到。所谓“对内存施加的影响”就是指对变量的写入,“被观测到”指当读取这个变量时能够得到刚才写入的值(如果中间没有发生其它的写入)。

 

下面是我列出的三条非常重要的happen-before规则,利用它们可以确定两个操作之间是否存在happen-before关系。

  1. 同一个线程中,书写在前面的操作happen-before书写在后面的操作。这条规则是说,在单线程 中操作间happen-before关系完全是由源代码的顺序决定的,这里的前提“在同一个线程中”是很重要的,这条规则也称为单线程规则 。这个规则多少说得有些简单了,考虑到控制结构和循环结构,书写在后面的操作可能happen-before书写在前面的操作,不过我想读者应该明白我的意思。
  2. 对锁的unlock操作happen-before后续的对同一个锁的lock操作。这里的“后续”指的是时间上的先后关系,unlock操作发生在退出同步块之后,lock操作发生在进入同步块之前。这是条最关键性的规则,线程安全性主要依赖于这条规则。但是仅仅是这条规则仍然不起任何作用,它必须和下面这条规则联合起来使用才显得意义重大。这里关键条件是必须对“同一个锁”的lock和unlock。
  3. 如果操作A happen-before操作B,操作B happen-before操作C,那么操作A happen-before操作C。这条规则也称为传递规则。

 

还有一种利用延迟加载实现懒汉式单例模式的例子:

 

public class Singleton4 {   
       
    private static class SingletonHolder {   
        public static final Singleton4 INSTANCE = new Singleton4();   
    }   
       
    private Singleton4() {}   
       
    public static Singleton4 getInstance() {   
        return SingletonHolder.INSTANCE;   
    }   
}  

 

 

推荐一篇好文:

http://soongbo.iteye.com/blog/1343683

分享到:
评论

相关推荐

    单例模式(饿汉模式、懒汉模式、DCL单例模式、枚举)

    本文将详细讨论四种常见的单例实现方式:饿汉模式、懒汉模式、双重检查锁定(DCL)单例模式以及枚举单例。 1. **饿汉模式**: 饿汉模式是在类加载时就完成了实例化,避免了线程同步问题。这种方式简单且安全,但...

    设计模式之单例模式(结合工厂模式)

    将单例模式与工厂模式结合,可以创建一个单例工厂,这个工厂类负责生成单例对象。这样做有两个主要好处:一是隐藏了单例的实现细节,使得代码更加整洁,降低了耦合度;二是可以通过工厂方法扩展新的实现,如果将来...

    C#单例模式详解 C#单例模式详解C#单例模式详解

    单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。在C#中,单例模式常用于管理共享资源或控制类的实例化过程,以提高性能、节约系统资源,特别是在整个应用程序生命周期内只需要一...

    单例模式详解~~单例模式详解~~

    单例模式是一种设计模式,它的主要目标是确保一个类只有一个实例,并提供一个全局访问点。在软件工程中,单例模式常用于控制资源的共享,比如数据库连接池、线程池或者日志系统等,这些资源通常需要全局唯一且高效地...

    设计模式——单例模式

    **设计模式——单例模式** 在软件工程中,设计模式是一种在特定场景下解决常见问题的标准方案,可以被复用并提升代码质量。单例模式是设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。这种模式...

    7种单例模式

    单例模式是软件设计模式中的一种经典模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如控制共享资源、管理配置对象等。下面将详细介绍七种常见的单例模式实现...

    单例模式和工厂模式代码

    在Java中,实现单例模式有多种方法,包括懒汉式(线程不安全)、饿汉式(静态常量)、双检锁(DCL)和枚举单例。其中,双检锁和枚举单例是线程安全的,推荐在多线程环境下使用。 ```java // 双检锁/双重校验锁(DCL...

    使用单例模式创建学生管理系统(饿汉式、懒汉式)

    单例模式是软件设计模式中的一种,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。在Java或类似的面向对象编程语言中,单例模式常用于管理共享资源,如数据库连接池、线程池或者配置文件等。在这个...

    几种单例模式demo

    单例模式是软件设计模式中的一种,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在很多场景下都非常有用,比如控制资源的唯一性、管理共享配置或者创建昂贵的对象时避免频繁创建销毁。 ...

    Java 单例模式 工具类

    Java中的单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供全局访问点。在Java编程中,单例模式常用于控制资源的访问,比如数据库连接池、线程池或者日志对象等。本篇文章将深入探讨如何在Java中...

    设计模式之单例模式源码demo

    3. **双重检查锁定(DCL,Double Check Locking)单例模式**:结合了饿汉模式和懒汉模式的优点,既延迟了初始化,又保证了线程安全。在多线程环境下,只有在`instance`为`null`时才会进入同步块,避免了不必要的同步...

    设计模式——单例模式(懒汉模式)

    下面是一个简单的DCL实现的懒汉式单例模式代码示例: ```java public class Singleton { private volatile static Singleton instance; // 使用volatile关键字防止指令重排序 private Singleton() {} public ...

    23钟设计模式之单例模式

    单例模式有多种实现方式,常见的包括懒汉式、饿汉式以及双重检查锁定(DCL)等。 1. 懒汉式:懒汉式是在第一次使用时才创建单例对象,以延迟加载提高效率。但是,如果在多线程环境下,没有正确处理同步问题,可能...

    单例模式的要点及模式

    ### 三、单例模式的应用场景与优缺点 **应用场景**: - 全局日志对象 - 数据库连接池 - 缓存服务 - 线程池 - 多线程环境下的线程同步控制 **优点**: - 节省内存空间,减少系统资源消耗。 - 避免对资源的多重占用...

    设计模式单例模式

    单例模式是软件设计模式中的一种基础且广泛应用的模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式在系统中需要频繁创建和销毁对象,且对象创建成本较高,或者需要共享资源的情况下非常...

    Java单例模式应用研究.pdf

    #### 五、双重检查锁(DCL)单例模式 双重检查锁单例模式(Doubly Checked Locking Singleton)是懒汉式单例模式的一种改进版,既实现了延迟加载,又解决了多线程安全问题,同时也减少了同步的开销。具体实现如下: ...

    大话设计模式--Singleton(单例模式)

    单例模式是软件设计模式中的一种经典模式,它在许多场景下被广泛使用,尤其是在需要全局唯一实例的情况下。本文将深入探讨单例模式的概念、作用、实现方式以及其在实际编程中的应用。 单例模式的核心思想是确保一个...

    单例模式各种实现方式

    单例模式是软件设计模式中的一种基础且广泛应用的模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。在Java中,实现单例模式有多种方法,每种都有其特定的优缺点和适用场景。以下是几种常见的单例...

    设计模式——策略模式 & 单例模式

    策略模式和单例模式是软件设计中两种非常重要的设计模式,它们在实际开发中有着广泛的应用。在这篇文章中,我们将深入探讨这两种模式的核心概念、实现方式以及如何在实际项目中运用。 策略模式是一种行为设计模式,...

    Java单例模式深入理解

    Java单例模式是一种设计模式,它允许在程序中创建唯一一个类实例,通常用于管理共享资源,例如数据库连接、线程池或者配置对象等。单例模式的核心在于限制类的构造函数,确保类只能被初始化一次,从而实现全局唯一的...

Global site tag (gtag.js) - Google Analytics