设计模式——单例模式(Singleton Pattern)实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a987073381/article/details/52145711
什么是单例模式?
单例模式(Singleton Parttern)保证一个类仅有一个实例,并提供一个访问它的全局访问点。类似于全局变量,但是效果比全局变量更优,全局变量必须在程序开始就创建,如果后面没有用到,会造成资源的浪费。

为什么要创建单例模式?
有一些对象我们只需要一个,比方说:线程池(threadPool)、缓存(cache)、对话框、注册表(registry)的对象、日志对象,充当打 字机,显卡等设备的驱动程序的对象。事实上,这些对象只能有一个实例,如果创造了过个实例,会导致很多问题,例如:程序的行为异常、资源使用过度,或发生不一致的后果。

单例模式的特点:
单例类只能有一个实例;
单例类必须自己创建这个实例;
单例类必须自行想整个系统提供实例;

单例模式的实现方式:
一般 构造函数声明为私有,用一个静态public来实例化对象,返回该类的实例,在外部通过调用这个方法来实例化对象。

一、饿汉式单例类
//饿汉式单例类在类初始化时自行实例化 
class singleton{  
private:  
    static singleton *instance;//用一个静态变量来记录该类的唯一实例  
    singleton(){};  

public:  
    //返回该类的实例
    static singleton* get_instance()  
    {   
        return instance;  
    }  
};  
singleton* singleton::instance = new singleton();//静态成员变量初始化 

二、饱汉(懒汉)式单例类
class singleton{  
private:  
    static singleton *instance;//用一个静态变量来记录该类的唯一实例  
    singleton(){};  

public:  
    //返回实例前先检查,如果没有创建,则先创建再返回该类的实例
    static singleton* get_instance()  
    {  
        if(NULL == instance)  <---两个线程同时运行到这
            instance = new singleton();  
        return instance;  
    }  
};  
singleton* singleton::instance = NULL;//静态成员变量初始化 

这里有个问题,如果在多线程环境下使用会出现问题,比如两个线程同时运行到代码所指位置,由于最初instance都是初始化为NULL,那么两个线程会同时进入到if里面然后创建出两个实例!这显然与单例模式不符,所以我们要对它进行实例化的代码进行互斥操作。


三、加互斥锁
通过加锁可以实现多个线程判断instance是否为空。
#include <iostream>  
#include <mutex>  
using namespace std;

mutex mtx;//互斥锁

class singleton{  
private:  
    static singleton *instance;//利用一个静态变量来记录Singleton的唯一实例  
    singleton(){};  

public:  
    //实例化对象的方法  
    static singleton* getInstance()  
    {  
        mtx.try_lock();//加锁函数  
        if(NULL == instance)
        {
            instance = new singleton();
        }
        mtx.unlock();//释放锁函数
        return instance;  
    }  
};  

singleton* singleton::instance = NULL;//静态成员变量初始化  

四、双重检测加锁
因为我们只需要在没有创建实例时对它进行加锁,如果已经创建实例则不需要再进行加锁操作。所以要在加锁前先判断一次实例是否已经创建。
mutex mtx;//互斥锁

class singleton{  
private:  
    static singleton *instance;//利用一个静态变量来记录Singleton的唯一实例  
    singleton(){};  

public:  
    //实例化对象的方法  
    static singleton* getInstance()  
    {  
        if(NULL == instance)
        {
            mtx.try_lock();//加锁函数  
            if (NULL == instance)
            {
                instance = new singleton();
            }
            mtx.unlock();//释放锁函数
        }
        return instance;  
    }  
};  

singleton* singleton::instance = NULL;//静态成员变量初始化  

参考:

猜你喜欢

转载自blog.csdn.net/a987073381/article/details/52145711