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

来源:互联网 发布:mac 抹掉磁盘名称 编辑:程序博客网 时间:2024/05/18 02:49

1. 什么是单例模式?

单例模式是设计模式中的一种,是设计模式中最简单,最常用的一种模式,这种模式用来保证某一个类的对象实例在应用中只有一个,即只被创建一次。在实际的开发中,我们经常会碰到只需要创建一个实例的情况,例如: 配置文件,日志对象,线程池,缓存等。这些实例为了保证一致性,在整个应用中只需要被创建一次,例如,如果日志对象被创建多次,那么很可能日志中的内容就不一致,还有就是有时候占用资源过多的一些对象被创建多次会浪费资源,比如线程池等。所以为了保证对象的单例,出现了单例模式。

2. 在C++中如何创建单例模式?

有两种具体创建单例模式的方法,分别是“饿汉模式”和“懒汉模式”。在讲解这两种方法之前,先介绍一下无论是C++,还是JAVA等OOP语言创建单例模式的一个整体思路:
step1: 将构造函数声明为私有的。
因为在创建一个对象的时候会去调用类的构造函数来完成对对象内存空间的分配以及成员的初始化,所以如果想限制对象的创建,首先应该禁止外界对象对构造函数的调用,通过这个办法就可以限制对象的创建。
step2: 在类中声明一个私有的静态的类的对象(实例)。
这个实例就是我们需要获得的,唯一的实例。之所以是static类型的是因为我们需要通过类直接获得而不通过对象获得,因为我们无法创建一个对象。同时从封装的角度,我们下面需要定义一个static类型的接口用来返回这个实例。
step3: 定义一个static类型的public类型的事例获取函数。
可以通过类直接调用这个函数获得类中定义的那个实例。
下面我们分别就这两种来讲解。
无论是通过“饿汉模式”还是“懒汉模式”上面的思路大致一样。

3. 饿汉模式。

饿汉模式,很形象,就是在类加载的时候已经创建好了类的实例,我们通过使用接口直接获得这个实例,所以我们可以看到,饿汉模式是一种线程安全的下面是我在C++中实现的:
#

include <iostream>     using namespace std;class Singleton{private:    Singleton(){}  //将构造函数定义为私有的,避免直接创建外部对象。    ~Singleton(){ delete sig;}    static Singleton *sig;  //声明一个私有的静态数据成员sig用来作为为一个实例。public:    static Singleton *getInstance()  //声明一个static类型的接口获得实例    {        return sig;    }};Singleton* Singleton::sig = new Singleton;  //在类外进行实例的定义和初始化int main(void){     Singleton *msg1 = Singleton::getInstance();  //创建两个实例     Singleton *msg2 = Singleton::getInstance();   //判读实例是否相等    if (msg1 == msg2)        cout << "Same Instance!\n";    else        cout << "Error in Creating Single Instance!\n";    return 0;}

4. 懒汉模式

懒汉模式的整个设计思想和饿汉模式是一样的,只是懒汉模式在类中只给出实例的声明并未给出定义。所以是当多个线程去竞争的时候是线程不安全的,所以需要使用锁机制,需要操作系统的配合,这里就不给出懒汉模式的线程安全了。

include <iostream>     using namespace std;class Singleton2{private:    Singleton2(){}    static Singleton2 *sig;   //只给出声明public:    static Singleton2* getInstance();};Singleton2* Singleton2::getInstance(){    if (sig == NULL)    {        sig = new Singleton2;    }    return sig;}Singleton2* Singleton2::sig;   //不初始化,和饿汉模式的区别。int main(void){    Singleton2 *msg1 = Singleton2::getInstance();  //创建两个实例     Singleton2 *msg2 = Singleton2::getInstance();   //判读实例是否相等    if (msg1 == msg2)        cout << "Same Instance!\n";    else        cout << "Error in Creating Single Instance!\n";    return 0;}

5. 饿汉和懒汉的区别

饿汉是在类加载的时候就已经完成了类的事例话,所以在加载的时候会被比较慢,但运行起来比较快,而且是线程安全的。
懒汉模式则和饿汉模式相反。
By Lingtao Kong In Nanjing 2015/04/15
http://blog.csdn.net/michael_kong_nju/article/details/45060527

0 0