1、单例模式
单例模式是指在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。
为什么需要单例模式
单例模式是为了保证程序的线程安全。
线程安全:
在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常安全地执行,不会出现数据的污染等情况。
如何保证线程安全:
(1)共享资源加锁,保证每一个资源变量在同一时刻只能有一个线程占用;
(2)每个线程拥有自己的私有资源,不去共享进程中的资源;
单例模式类图:
单例模式的特点:
(1)构造函数和析构函数为私有类型,目的是禁止外部构造和析构;
(2)拷贝构造函数和赋值构造函数是私有类型,目的是禁止外部拷贝和赋值,确保实例的唯一性;
(3)类中有一个获取实例的静态方法,可以全局访问;
2、单例模式实现
1> 局部静态变量实现
/* 局部静态变量实现 */
class Singleton
{
public:
static Singleton& GetInstance()
{
static Singleton _s_instance;
return _s_instance;
}
protected:
Singleton() = default;
~Singleton() = default;
private:
/*
拷贝和赋值构造函数声明为delete时,访问修饰符声明为public、protected、private均可
Singleton(const Singleton&) = delete;
Singletone& operator=(const Singleton&) = delete;
*/
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
};
这种方法存在问题:在多线程场景下还是有可能会存在线程安全的问题,因为多线程同时调用GetInstance方法有可能还是会产生竞争。
解决方法:在程序的单线程启动阶段就调用GetInstance方法。
2> 通过call_once实现
class Singleton
{
public:
static std::shared_ptr<Singleton> GetInstance();
~Singleton() = default;
private:
Singleton() = default;
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
private:
static std::shared_ptr<Singleton> _s_instance;
static std::once_flag _s_once_flag;
};
std::shared_ptr<Singleton> Singleton::_s_instance = nullptr;
std::once_flag Singleton::_s_once_flag;
std::shared_ptr<Singleton> Singleton::GetInstance()
{
std::call_once(_s_once_flag, [&] {
_s_instance = std::shared_ptr<Singleton>(new Singleton());
});
return _s_instance;
}
说明:
上述单例利用std::call_once和std::once_flag实现,std::call_once的调用是线程安全。