1、单线程中的单例模式
class Singleton
{
public:
Singleton* Getinstance()
{
if (m_instance == nullptr)//判断是否为空
{
m_instance = new Singleton();//实例化一个对象
std::atexit(Destructor);//保证程序退出时对象正常析构
}
return m_instance;//返回
}
private:
//私有化各类构造函数
Singleton(){}//普通构造
Singleton(const Singleton& s){}//拷贝构造
Singleton& operator= (const Singleton& s){}//赋值构造
~Singleton(){}//私有化析构函数,防止被外部调用
private:
static void Destructor()//析构回调函数
{
if (m_instance != nullptr)
{
delete m_instance;
m_instance = nullptr;
}
}
private:
static Singleton* m_instance;//声明静态实例
};
Singleton* Singleton::m_instance = nullptr;//初始化静态实例
2、多线程环境下的单例模式
实现方式1:
该方式在多线程获取实例时,直接采用加互斥锁的方式,防止其他线程同时访问空的实例,导致实例被new多份。
class Singleton_MultiThread
{
public:
Singleton_MultiThread* Getinstance()
{
std::lock_guard<std::mutex> lock(m_mtx);//直接在判断前加锁,加锁粒度大,性能较差
if (m_instance == nullptr)//判断是否为空
{
m_instance = new Singleton_MultiThread();//实例化一个对象
std::atexit(Destructor);//保证程序退出时对象正常析构
}
return m_instance;//返回
}
private:
//私有化各类构造函数
Singleton_MultiThread(){}//普通构造
Singleton_MultiThread(const Singleton_MultiThread& s){}//拷贝构造
Singleton_MultiThread& operator= (const Singleton_MultiThread& s){}//赋值构造
~Singleton_MultiThread(){}//私有化析构函数,防止被外部调用
private:
static void Destructor()//析构回调函数
{
if (m_instance != nullptr)
{
delete m_instance;
m_instance = nullptr;
}
}
private:
static Singleton_MultiThread* m_instance;//声明静态实例
static std::mutex m_mtx;
};
Singleton_MultiThread* Singleton_MultiThread::m_instance = nullptr;
std::mutex Singleton_MultiThread::m_mtx;
实现方式2:
由于方式1每次获取都需要加锁,多线程同时访问时导致线程等待,造成性能问题。由于多线程环境下,我们只需要在实例为空时new一次就好,不需要每次都进行加锁,为此采用方式2。由于CPU或编译器会对代码进行指令重排或优化,由此加入了内存屏障和原子操作,防止因为编译器或者CPU的指令重排导致获取实例有问题,保障程序执行顺序是按照我们预期的代码顺序进行执行,同时提升了多线程访问的性能。
class Singleton_opt
{
public:
static Singleton_opt* Getinstance()
{
//加入原子操作和内存屏障,防止CPU的指令优化(指令重排)而导致获取的实例对象有问题
//std::lock_guard<std::mutex> lock(m_mtx);//直接在判断前加锁,加锁粒度大,性能较差
Singleton_opt* tmp = m_instance.load(std::memory_order_relaxed);//取得原子变量
std::atomic_thread_fence(std::memory_order_acquire);//内存屏障,保证获取tmp的值不被CPU优化到后面执行
if (tmp == nullptr)//判断是否为空
{
std::lock_guard<std::mutex> lock(m_mtx);
tmp = m_instance.load(std::memory_order_relaxed);
if (tmp == nullptr)
{
tmp = new Singleton_opt();//实例化一个对象
std::atomic_thread_fence(std::memory_order_release);//释放内存屏障
m_instance.store(tmp, std::memory_order_relaxed);//将tmp的值存入m_instance
std::atexit(Destructor);//保证程序退出时对象正常析构
}
}
return tmp;//返回
}
private:
//私有化各类构造函数
Singleton_opt(){}//普通构造
Singleton_opt(const Singleton_opt& s){}//拷贝构造
Singleton_opt& operator= (const Singleton_opt& s){}//赋值构造
~Singleton_opt(){}//私有化析构函数,防止被外部调用
private:
static void Destructor()//析构回调函数
{
Singleton_opt* tmp = m_instance.load(std::memory_order_relaxed);
if (tmp != nullptr)
{
delete tmp;
tmp = nullptr;
m_instance.store(tmp, std::memory_order_relaxed);
}
}
private:
static std::atomic<Singleton_opt*> m_instance;//声明静态实例
static std::mutex m_mtx;
};
std::atomic<Singleton_opt*> Singleton_opt::m_instance;
std::mutex Singleton_opt::m_mtx;
以上,是单线程和多线程环境下的单例模式,请读者批评指正。