C++ 饿汉式单例模式_双重锁

C++ 饿汉式单例模式_双重锁

1、单例模式定义

保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局 访问方法。 (GoF给出单例模式的定义)
用例图

2、单例模式三个要点

(1)某个类只能有一个实例;
(2)它必须自行创建这个实例;
(3)它必须自行向整个系统提供这个实例
在单例类的内部实现只生成一个实例,同时它提供 一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;
为了防止 在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个 Singleton类型的静态对象,作为外部共享的唯一实例。

3、单例模式的使用步骤

(1)构造函数私有化。
(2)提供一个全局的静态方法(全局访问点)来获取单例对象。
(3)在类中定义一个静态指针,指向本类的变量的静态变量指针 。

4、单例模式的优缺点

优点:
(1) 单例模式提供了对唯一实例的受控访问。
(2) 节约系统资源。由于在系统内存中只存在一个对象。
缺点:
(1) 扩展略难。单例模式中没有抽象层。
(2) 单例类的职责过重。

5、适用场景

(1) 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器 或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。
(2) 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问 点,不能通过其他途径访问该实例。

6、代码实例

提供了两个释放单例的方式:

//#define UseManual
为自动释放
#define UseManual
手动释放

完整代码:

#include <iostream>
#include<vector>
#include<mutex>
using namespace std;

//懒汉式单例
class CSingleton
{
//#define UseManual
public:
    //提供实例对象的唯一接口
    static CSingleton* GetInstance()
    {
        if(m_pInstance == nullptr)
        {
            mux.lock();  // 双重锁检查
            if(m_pInstance == nullptr)
            {
                m_pInstance  = new CSingleton();
            }
            mux.unlock();
        }
        m_count ++;  //被使用的次数
        return m_pInstance;
    }
    
#ifdef UseManual
    static void destroyInstance()  //当程序结束时候手动调用
    {
        if(m_pInstance != nullptr)
        {
            delete  m_pInstance ;
        }
        m_pInstance = nullptr;
    }

#endif
  
    void disPlay()
    {
        cout<<"m_count = "<<m_count<<endl <<"&this =" <<this<<endl;
    }

private:
    //构造函数私有化
    CSingleton(){
        cout<<"CSingleton"<<endl;
    };
    ~CSingleton(){

        cout<<"~CSingleton"<<endl;
    };
    //私有化将被唯一实例化的对象
    static CSingleton* m_pInstance;
    //实例化计数器
    static int m_count;
    //多线程的互斥锁
    static mutex mux;
#ifndef UseManual
    class CGarbo //它的唯一工作就是在析构函数中删除CSingleton的实例
    {
    public:
        ~CGarbo()
        {
            cout<<" ~CGarbo"<<endl;
            if( CSingleton::m_pInstance!=NULL )
            {
                delete CSingleton::m_pInstance;
                CSingleton::m_pInstance = nullptr;
            }
        }

    };
    //定义一个静态成员,程序结束时,系统会自动调用它的析构函数
    static CGarbo Garbo; 
#endif
};
CSingleton* CSingleton:: m_pInstance = NULL;
int CSingleton:: m_count = 0;
mutex CSingleton::mux;
void fun(uint32_t num)
{
    CSingleton *tmpSg= CSingleton::GetInstance();
    tmpSg->disPlay();
    cout <<"threadId = " << this_thread::get_id()<< "  num = " << num << endl ;
}
int main()
{
    //使用一组线程去实例化CSingleton 对象
    vector<thread>  vthread;
    for(int i = 0 ; i < 10; i++)
    {
        vthread.push_back(thread(fun,i));
    }
    for(thread &t:vthread)
    {
        t.detach();
    }
    cout<<"应用程序结束"<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值