单例模式
文章目录
单例模式解析
动机/需求来源
面像对象解决了“抽象”的问题,但是有时会有一些性能损失。
需要保证在系统中只存在一个实例,保证逻辑正确和较好的效率。
绕过常规构造器,提供只能生成一个实例的机制,承担类设计者的责任。
设计要点
- 构造函数和拷贝构造函数都是私有private
- 静态变量,指向自身的指针
- 静态函数,获取instance
- 线程安全和线程非安全
- 多线程环境下:双检查锁
- 内存reorder下双检查锁的失效(待阅读整理!)
C#下的单例模式
C#知识点
-
静态构造函数:第一次被使用之前自动调用,且保证只调用一次。
-
struct 和 class,未指定时,默认都是private。
-
静态构造函数先初始化静态变量,再执行函数体内语句。再执行普通构造函数,构造函数先初始化成员变量,再执行函数体内语句。
-
待增加具体的实现方法
C++下的单例模式
class MySingleton
{
public:
static MySingleton* getInstanceSingleThread(); //非线程安全版本,仅适用于单线程
static MySingleton* getInstanceMultiThreadSlow(); //单纯加锁,安全但是效率低
static MySingleton* getInstanceMultiThreadEfficient(); //双重检查加锁 DCLP,存在内存reorder 的风险
static MySingleton* getInstanceMultiThreadEfficientAndSafe(); //安全的多线程版本
static MySingleton* mInstance;
private:
MySingleton() { cout << "singleton constructor."<<endl; } //私有构造函数
MySingleton(const MySingleton& obj) { cout << "singleton copy constructor" << endl; } //私有拷贝构造
};
非线程安全版本
inline MySingleton* MySingleton::getInstanceSingleThread()
{
if (mInstance==nullptr)
{
mInstance = new MySingleton();
}
return mInstance;
}
单纯加锁,安全但效率低
inline MySingleton * MySingleton::getInstanceMultiThreadSlow()
{
//Lock lock;
if (mInstance == nullptr)
{
mInstance = new MySingleton();
}
return mInstance;
}
双重检查,DCLP,但存在内存reorder风险
inline MySingleton * MySingleton::getInstanceMultiThreadEfficient()
{
if (mInstance == nullptr)
{
//Lock lock;
if (mInstance == nullptr)
{
mInstance = new MySingleton(); //1分配内存、2执行构造函数、3传回地址给指针; 是假想的顺序。但是,编译器有可能将该顺序给优化了
} //如果1分配内存之后直接传回地址给指针,此时另一个线程判断mInstance不为空,就拿去用,会内存出错(因未初始化)。
}
return mInstance;
}
安全的多线程方法
//https://www.bilibili.com/video/av24176315?p=12
std::atomic<MySingleton*> MySingleton::mInstance;
std::mutex MySingleton::m_mutex;
inline MySingleton * MySingleton::getInstanceMultiThreadEfficientAndSafe()
{
MySingleton* tmp = mInstance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (tmp == nullptr)
{
std::lock_guard<std::mutex> lock(m_mutex);
tmp = mInstance.load(std::memory_order_relaxed);
if (tmp == nullptr)
{
tmp = new MySingleton;
std::atomic_thread_fence(std::memory_order_release);
mInstance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
tomic_thread_fence(std::memory_order_release);
mInstance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}