单例模式:存在一种特殊的类,保证在系统中只存在一个实例,以此确保程序的逻辑正确性、良好的效率。
#include <iostream>
using namespace std;
class Singleton{
private:
Singleton(){}//定义构造函数在private中,防止生成合成的默认构造函数
Singleton(const Singleton&);//定义拷贝构造函数在private中,目的与上述一致,防止类外使用合成的拷贝函数使实例化
public:
static Singleton* getInstance();
static Singleton* m_instance;
};
Singleton* Singleton::m_instance=nullptr;
//单线程下实现单例模式,比较高效,但是如果在多线程下,会出错,会有线程同时进入25行代码,导致产生多个实例
Singleton* Singleton::getInstance(){
if(m_instance==nullptr){
m_instance=new Singleton();
}
return m_instance;
}
//多线程下安全的实现单例模式,但是会降低效率,因为可能m_instance不为空,但也只能通过锁只能一个线程访问
Singleton* Singleton::getInstance(){
lock lock;//加锁,使多线程下安全使用单例模式
if(m_instance==nullptr){
m_instance=new Singleton();
}
return m_instance;
}
//双检查锁,但由于内存读写reorder(编译器优化过程)不安全
//编译器优化过程:本来第46行大致步骤为1开辟内存,2调用Singleton构造函数对内存处理,3将内存地址给m_instance;但编译器优化可能导致执行步骤为132导致错误
Singleton* Singleton::getInstance(){
if(m_instance==nullptr){
lock lock;
if(m_instance==nullptr){//这个检查有必要,因为如果m_instance如果为空,多个线程在42准备进锁,如果不再次检查,多个线程会不断进锁并不断创建实例
m_instance=new Singleton();
}
}
return m_instance;
}
//C++11之后机制
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;
Singleton* Singleton::getInstance(){
Singleton* tmp=m_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acqurire);//获取内存fence,不让编译器reorder
if(tmp==nullptr){
std::lock_guard<std::mutex>lock(m_mutex);
tmp=m_instance.load(std::memory_order_relaxed);
if(tmp==nullptr){
tmp=new Singleton;
std::atomic_thread_fence(std::memory_order_release);//释放内存fence
m_instance.store(tmp,std::memory_order_relaxed);
}
}
return tmp;
}
模式定义:保证一个类只有一个实例,并提供一个该实例的全局访问点