1.单例模式
单例模式有两种
1.1 懒汉模式(线程不安全)
需要用到对象的时候才开始创建,多个线程调用的时候可能会创建多个对象
1.2 饿汉模式(线程安全)
一开始就创建一个对象
将构造函数私有化,不允许外部构造,声明一个静态的类指针,和静态的getInstance()函数,通过域名调用getInstance()函数来创建类对象
2.饿汉模式
class Singleton
{
public:
// 获取单实例
static Singleton* GetInstance()
{
return g_pSingleton;
};
// 释放单实例,进程退出时调用
static void deleteInstance()
{
if (g_pSingleton)
{
delete g_pSingleton;
g_pSingleton = nullptr;
}
};
private:
// 将其构造和析构成为私有的, 禁止外部构造和析构
Singleton() {};
~Singleton() {};
//禁用拷贝构造和赋值构造
Singleton(const Singleton &signal)=delete;
const Singleton &operator=(const Singleton &signal)=delete;
private:
// 唯一单实例对象指针
static Singleton *g_pSingleton;
};
Singleton *Singleton::g_pSingleton = new Singleton;
3.懒汉模式(线程安全,加锁)
class Singleton
{
public:
// 获取单实例
static Singleton* GetInstance()
{
if (g_pSingleton == nullptr)
{
unique_lock<mutex> lock(m_mtx);
if (g_pSingleton == nullptr)
{
volatile auto temp = new Singleton;
g_pSingleton = temp;
/*
因为在并发场景下可能会出现问题。
singleton 对象在初始化的时候实际上是分三步的:
1. 先申请一块内存;
2. 再调用构造函数进行初始化;
3. 将内存地址赋值给 singleton 。
但是上述操作在不同编译器上表现可能是不一样的,可能先将内存地址赋值给 singleton ,
再调用构造函数进行初始化。那在并发场景下,线程拿到的 singleton 可能是还未构造完成的单例对象,在使用时可能出现问题。
先赋值给 temp 在赋值给 singleton ,可以保证返回的单例对象一定是初始化完成的。
*/
}
}
return g_pSingleton;
};
// 释放单实例,进程退出时调用
static void deleteInstance()
{
unique_lock<mutex> lock(m_mtx);
if (g_pSingleton)
{
delete g_pSingleton;
g_pSingleton = nullptr;
}
};
private:
// 将其构造和析构成为私有的, 禁止外部构造和析构
Singleton() {};
~Singleton() {};
//禁用拷贝构造和赋值构造
Singleton(const Singleton &signal)=delete;
const Singleton &operator=(const Singleton &signal)=delete;
private:
// 唯一单实例对象指针
static Singleton *g_pSingleton;
static mutex m_mtx;
};
Singleton *Singleton::g_pSingleton = nullptr;
4.懒汉模式(c++11线程安全 :call_once)
call_once:保证函数只被执行一次。
#include <iostream>
#include <memory>
#include <mutex>
class Singleton {
public:
static std::shared_ptr<Singleton> getSingleton();
~Singleton() {};
private:
Singleton() { };
};
static std::shared_ptr<Singleton> singleton = nullptr;
static std::once_flag singletonFlag;
std::shared_ptr<Singleton> Singleton::getSingleton() {
std::call_once(singletonFlag, [&] {
singleton = std::shared_ptr<Singleton>(new Singleton());
});
return singleton;
}