线程安全的单例模式(C++11/静态局部变量)
请用C++实现线程安全的单例模式(Singleton),说明C++11静态局部变量初始化保证的线程安全性(Meyer's Singleton),以及饿汉式、双重检查锁定模式(DCLP)的优缺点。
回答
编译有声
Meyer's Singleton(C++11及以后,最推荐):
class Singleton {
public:
static Singleton& instance() {
static Singleton inst; // C++11保证线程安全初始化
return inst;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() = default;
~Singleton() = default;
};
C++11规定:函数中static变量初始化在首次控制流经过时,由编译器保证线程安全(类似std::call_once)。
饿汉式:
class Singleton {
static Singleton inst; // 程序启动时初始化
public:
static Singleton& instance() { return inst; }
};
Singleton Singleton::inst; // 静态成员定义
线程安全,但在多动态链接库场景有初始化顺序问题。
双重检查锁定(DCLP)(不推荐):
static Singleton* volatile inst = nullptr;
if (!inst) { // 第一次检查
std::lock_guard lk(mtx);
if (!inst) inst = new Singleton(); // 第二次检查
}
// 存在指令重排序问题(new的步骤被重排),需atomic+acquire/release
DCLP在C++11前有问题(指令重排导致返回未完全构造的对象),C++11后可用atomic修复但已没有必要(Meyer's更简洁)。