单例模式(Singleton Pattern)属于创建型模式。保证一个类仅有一个实例,并提供一个访问它的全局访问点。
- 懒汉式:在需要用到实例时才创建实例,普通懒汉式不支持多线程,加锁的懒汉式效率比较低
- 饿汉式:类加载时就创建实例,在没使用到实例时会浪费内存
下面是一份单例模式的模板类代码,通过atomic实现线程安全的懒汉式单例
template <class T>
class Singleton : public NonCopyable{
//不可复制构造
private:
static T *s_singleton; //储存实例的指针
static std::atomic_flag s_instantiated; //是否已实例化,原子布尔,保证多线程安全
static volatile bool s_instantiating; //是否正在实例化中,volatile多变的
public:
static T* instance(){
//懒汉式
if (!s_instantiated.test_and_set()){
//test_and_set 设置flag为true,返回值是设置之前的flag值
s_singleton = new T(); //构造对象
s_instantiating = false; //实例创建完成
}
while (s_instantiating);
return s_singleton;
}
template <typename ...P>
static T* instance(P... args){
if (!s_instantiated.test_and_set()){
s_singleton = new T(args...);
s_instantiating = false;
}
while (s_instantiating);
return s_singleton;
}
};
template<typename T>
T* Singleton<T>::s_singleton = nullptr;
template<typename T>
std::atomic_flag Singleton<T>::s_instantiated = ATOMIC_FLAG_INIT;
template<typename T>
volatile bool Singleton<T>::s_instantiating = true;
}
- 补充问题
在此模板中可能出现单例嵌套,导致
在s_singleton = new T(); //此处构造对象 ,在对象构造过程中再次调用了instance s_instantiating = false; //实例创建完成
while (s_instantiating);
处循环