C++单例模式线程安全的最佳实践
请给出C++中双检锁(DCLP)单例的线程安全实现,并说明为什么需要std::atomic。
回答
我还是少年
双检锁需要std::atomic和内存序防止指令重排:
class Singleton {
static std::atomic<Singleton*> instance;
static std::mutex mtx;
public:
static Singleton& getInstance() {
Singleton* p = instance.load(std::memory_order_acquire);
if (!p) {
std::lock_guard lock(mtx);
p = instance.load(std::memory_order_relaxed);
if (!p) {
p = new Singleton();
instance.store(p, std::memory_order_release);
}
}
return *p;
}
};
不使用atomic的问题:new Singleton()包含分配内存+构造+赋值三步,CPU可能重排导致另一线程读取到未构造的指针。acquire-release防止了这种重排。
C++11起更推荐Meyers Singleton,更简洁安全。