C++线程安全的单例类

单例模式是一种非常常用的设计模式,几乎在稍大的工程项目中都会用到。单例类保证在全局中只有唯一一个类的实例对象,并且在类的内部提供了获取这个唯一实例的接口。在类中,实例化出一个对象需要调用构造函数,为了防止在类的外部调用构造函数构造出实例,对类的构造函数就应有所限制,可以将构造函数的访问权限设置为private或protected。还要提供一个访问实例的接口,在类中定义一个static函数,返回类内部唯一的实例对象即可。
--------------------- 
 

#include <mutex>

class Singleton
{
private:
    Singleton()   //构造函数声明为私有的
        :_a(0)
    {}

    //防拷贝
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);

public:
    static Singleton* GetInstance()   //声明一个静态类型的接口来获取实例
    {
        if (_instance== NULL)
        {
            lock_guard<mutex> lock(_mtx);
            if (_instance== NULL)
            {
                _instance = new Singleton();
            }
        }
        return _instance;
    }

    void DelInstance()   //销毁实例
    {
        lock_guard<mutex> lock(_mtx);
        if (_instance)
        {
            delete _instance;
            _instance = NULL;
        }
    }

private:
    int _a;

    static Singleton* _instance;//声明一个静态成员作为类的实例
    static mutex _mtx;//保证线程安全的互斥锁
};

Singleton* Singleton::_instance = NULL;   //初始化静态成员变量
mutex Singleton::_mtx;

以上代码中加了互斥锁,保证了线程安全。但也不是绝对安全的,因为加锁或解锁会引入新的问题,有可能抛异常或者造成死锁。解决了线程安全,那么就可以进一步提高效率。在上述代码中,可以看到用了两次判断,也叫双检查机制,这就保证了只在第一次获取对象时加锁,避免高并发场景下每次获取实例对象都进行加锁,提高了效率。
--------------------- 
懒汉模式:在第一次调用GetInstance的时候才实例化出对象,此后返回的都是该对象。相对饿汉模式而言,复杂,要确保线程安全问题,但在各种场景下都适用。 
饿汉模式:无论是否需要该类的实例,在程序一开始的时候会产生该类的实例对象,此后返回的都是该对象。由于是在main函数之前创建线程,可能会出现不确定问题,适用性受到限制。 
上面代码实现的是懒汉模式,那么下边就实现饿汉模式
--------------------- 
 

namespace Hungry
{
    class Singleton
    {
    private:
        Singleton()   //构造函数声明为私有的
            :_a(0)
        {}

        //防拷贝
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);

    public:
        //static Singleton& GetInstance()   
        //{
        //  assert(_instance);
        //  return *_instance;
        //}

        static Singleton& GetInstance()     //在类内部创建静态实例,全局只此一份
        {
            static Singleton _instance;  
            return _instance;
        }

        void DelInstance()   //销毁实例
        {
            if (_instance)
            {
                delete _instance;
                _instance = NULL;
            }
        }

    private:
        int _a;

        static Singleton* _instance;
    };

    Singleton* Singleton::_instance = NULL;   
    //Singleton* Singleton::_instance = new Singleton();//全局生成一个实例对象   
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值