单线程方式
单线程的情况下非常简单,直接判断指针是否为空皆可。
static Singleton* instance() {
if (nullptr == s_instancePtr) {
s_instancePtr = new Singleton();
}
return s_instancePtr;
}
显然,这份代码无法应对多线程的情况。
比如当两个线程同时访问该函数时,指针都为空都会进入 if 条件并进行了两次 new 操作。对整个软件程序可能会造成不可估计的后果。

无脑上锁
我们都知道,对于多线程的情况下,上锁是一种最直接且有效的方式。
在这里直接无脑上锁便可以解决该问题。
#include <mutex>
class Singleton {
private:
static Singleton* s_instancePtr;
static std::mutex s_mutex;
public:
static Singleton* instance() {
std::lock_guard<std::mutex> lock(s_mutex);
if (nullptr == s_instancePtr) {
s_instancePtr = new Singleton();
}
return s_instancePtr;
}
private:
// 省略构造函数的处理
};
Singleton* Singleton::s_instancePtr = nullptr;
std::mutex Singleton::s_mutex;
虽然我们解决了多线程的问题。
在实例构造完成后,后续每次程序调用单例的时候的上锁。但上锁是一个开销很大的操作,因此在高并发的程序中,这种方式会一定程度上的影响程序的运行效率。