`
chriszeng87
  • 浏览: 738647 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线程安全的单例模式

阅读更多

    老大一直说要用这个来做面试题,让面试的人来写一个线程安全的单例模式,感觉自己还没掌握,把 Head first--Design Patterns 找了出来,以下大部分内容抄袭自这本书,略有增删改。

 

1. 全局变量的缺点:

 

   必须在程序一开始就创建好对象,如果程序在这次的执行过程中又一直没用到它,就非常耗费资源。

 

2. 经典的单例模式实现:

 

 

public class Singleton { 
      //用一个静态变量来记录Singleton类的唯一实例
      private static Singleton uniqueInstance;
 
      private Singleton() {}
        
      //注意这个方法也是静态的
      public static Singleton getInstance() { 
      	   if(uniqueInstance == null) {
           	 uniqueInstance = new Singleton();
           }
           return uniqueInstance;
      }
}
 

 

 

    单例常被用来管理共享的资源,例如数据库连接、线程池、缓存、注册表。

    单例模式确保一个类只有一个实例,并提供一个全局访问点。

 

    这个模式的问题:在多线程时,并不能保证这个类只被实例化一次。

 

3. 处理多线程:

 

    public class Singleton {

    //用一个静态变量来记录Singleton类的唯一实例
    private static Singleton uniqueInstance;
 
    private Singleton() {}
        
    //注意这个方法也是静态的
    public static synchronized Singleton getInstance() { 
        if(uniqueInstance == null) {
             uniqueInstance = new Singleton();
         }
         return uniqueInstance;
    }
}
 

   通过增加synchronized关键字到getInstance()方法中,迫使每个线程在进入方法之前,要先等别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。

 

   这种方法存在的问题:只有第一次执行此方法时,才真正需要同步。换句话说,一旦设置好uniqueInstance变量,就不再需要同步这个方法了。之后每次调用这个方法,同步都是一种浪费。

 

4.改善多线程

 

4.1 如果getInstance()的性能对应用程序不是很关键,就不用优化了

 

4.2 使用急切创建实例,而不用延迟实例化的做法

 

 

public class Singleton { 

    private static Singleton uniqueInstance = new Singleton();
 
    private Singleton() {}
        
    public static Singleton getInstance() { 
         return uniqueInstance;
    }
}
 

   标红的语句在静态初始化器(static initializer)中创建单例,这保证了线程安全

   利用这个做法,JVM在加载这个类时马上创建此唯一的单件实例。JVM保证任何线程访问uniqueInstance静态变量之前,一定先创建些实例。

 

   4.3 用“双重检查加锁”,在getInstance()中减少使用同步

 

    首先检查实例是否已经创建,如果尚未创建,才进行同步。这样一来,只有第一次会同步,这正是我们想要的。

 

 

public class Singleton { 

    private volatile static Singleton uniqueInstance;
 
    private Singleton() {}
        
    public static Singleton getInstance() { 
	if(uniqueInstance == null) { //(1)
        //只有第一次才彻底执行这里的代码
	   synchronized() {
	      //再检查一次
	      if(uniqueInstance == null)
		uniqueInstance = new Singleton();
   	   }
	}
         return uniqueInstance;
    }
}
 

   在最开始如果有1、2、3个线程走到了(1)处,假设1进入了同步块,2、3等待。1实例化后,2进入同步块,发现uniqueInstance已经不为空,跳出同步块。接着3进入,又跳出同步块。

 

    volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地uniqueInstance变量。如果性能是你关心的重点,那么这个做法可以帮你大大地减少getInstance()的时间耗费。

0
1
分享到:
评论
2 楼 chriszeng87 2011-06-09  
Technoboy 写道
貌似有点问题

应该没有吧
1 楼 Technoboy 2011-06-06  
貌似有点问题

相关推荐

    Qt线程安全单例模式写日志模式

    保证一个类只有一个实例,并提供一个访问它的全局访问点,使得系统中只有唯一的一个对象实例,具有线程安全,多线程测试通过。 1.打开日志并创建日志文件夹 默认为程序启动路径 2.清理日志文件下日志数量 默认保留90...

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

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

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

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

    c++线程安全单例模式

    c++单例模式, 需要boost中的function、bind、shared_ptr支持; 很好用; 下载中含简单的测试代码; 原帖:http://blog.csdn.net/CDScan/archive/2009/11/21/4848084.aspx

    线程安全单例

    然而,在多线程环境下,如果单例模式实现不当,则可能导致线程安全问题。因此,实现线程安全的单例模式就显得尤为重要。 #### 实现方法 给定的代码示例采用了一种称为“懒汉式”的单例模式实现方式,同时利用了...

    多线程单例模式并发访问

    ### 多线程单例模式并发访问 #### 一、多线程基础概念 在讨论多线程单例模式及并发访问之前,我们先来了解一些基本概念。 **进程**和**线程**是计算机科学中的两个核心概念,它们之间的关系紧密而复杂。 - **进程...

    详解python实现线程安全的单例模式

    然而,如果我们想要在类级别实现线程安全的单例模式,就需要考虑多线程环境下的并发问题。 在给出的代码中,首先定义了一个装饰器`Singleton`,它的目的是确保每次调用时返回的是同一个实例。装饰器内部维护了一个...

    Java中懒汉单例设计模式线程安全测试

    Java中懒汉单例设计模式线程安全测试,单例设计模式的测试

    老生常谈C++的单例模式与线程安全单例模式(懒汉/饿汉)

    1 教科书里的单例模式 我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法...

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

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

    C++ 多线程和多线程下的单例模式

    本资源描述了C++11 中多线程的创建,C++11中std命名空间中将boost库中的Thread加入,boost多线程从准标准变为标准,其中还介绍了C++ 多线程下的单例模式的使用,本文档为txt文档

    java多线程之线程安全的单例模式

    在多线程环境下,线程安全的单例模式尤其重要,因为如果不正确地实现,可能会导致多个线程创建多个实例,违反了单例模式的基本原则。本文将详细介绍Java中线程安全的单例模式,包括懒汉式和饿汉式两种实现方式。 1....

    43丨单例模式(下):如何设计实现一个集群环境下的分布式单例模式?1

    线程唯一的单例模式,又称为线程局部单例,是指在同一个线程内保证单例的唯一性,而在不同线程之间可以有各自的实例。实现线程唯一单例通常可以通过使用`ThreadLocal`变量。`ThreadLocal`为每个线程都维护了一个独立...

    单例模式线程安全的三种表达

    单例模式三种线程安全的表达方式,其中枚举方式的单例是最安全的

    线程安全的单例模式的几种实现方法分享

    线程安全的单例模式是设计模式中的一种经典实现,主要目标是在多线程环境下确保一个类只有一个实例,并提供全局唯一的访问点。以下是对几种线程安全单例模式实现方式的详细解释: 1. **饿汉式单例**: 饿汉式单例...

    Java 单例模式线程安全问题

    Java 单例模式线程安全问题详解 Java 单例模式线程安全问题是指在 Java 中实现单例模式时,如何确保线程安全的问题。单例模式是指在整个应用程序生命周期中,只有一个实例存在的设计模式。这种模式可以提高性能,...

    详解C++实现线程安全的单例模式

    总结来说,C++实现线程安全的单例模式通常涉及到对实例化过程的控制,以确保在多线程环境下只有一个实例存在。饿汉模式在类加载时完成实例化,是线程安全的,而懒汉模式需要额外的同步机制如互斥锁来保证线程安全。...

    c++单例模式线程日志类

    在这个特定的场景中,我们讨论的是一个实现了单例模式的日志类,该类专为多线程环境设计,具备日志等级控制、精确的时间戳以及可变长参数和标准格式化输出的功能。 首先,让我们深入了解单例模式。单例模式的主要...

Global site tag (gtag.js) - Google Analytics