C++单例模式
- Lazy Singleton(单例模式一般写法 )
class Singleton {
private:
Singleton();
~Singleton();
Singleton(const Singleton & rhs);
Singleton& operator=(const Singleton & rhs);
public:
static Singleton& getInstance()
{
if (instance == nullptr) {
instance = new Singleton;
}
return instance;
}
private:
static Singleton * instance;
};
说明:getInstance() 返回引用而不是指针,可以防止指针在外部被 delete 掉。而且,直到 getInstance() 被访问,才会new一个实例,所以被称为Lazy Singleton。
但是,Lazy Singleton不是线程安全的,很容易理解,当线程A和线程B都通过了 instance == nullptr 的判断,那么线程A和线程B都会创建新的实例,破坏了唯一性。
- Meyers Singleton
Effective C++ Item 04 上提到的一种实现。把 non-local static 对象替换为 local static 对象。因为 C++ 保证 local static 对象会在该函数被调用期间首次遇到该对象时进行初始化。
同时,C++0x之后,这种实现方式编译器将保证是线程安全的。
class Singleton {
private:
Singleton();
~Singleton();
Singleton(const Singleton & rhs);
Singleton& operator=(const Singleton & rhs);
public:
static Singleton& getInstance()
{
static Singleton instance;
return instance;
}
};
- 双检测锁模式(Double-Checked Locking Pattern)
也就是说,在判断 instance == nullptr 前加锁,但是加锁是有开销的,可以稍加修改代码,使得只在第一次创建实例时加锁。
static Singleton& getInstance()
{
if (instance == nullptr) {
Lock lock; // 在作用域范围内加锁,离开作用域自动析构
if (instance == nullptr) {
instance = new Singleton;
}
return *instance;
}
}
C++11中,标准库提供了原子操作,一种DCLP实现如下:(参考自这里)
class Singleton {
private:
Singleton();
~Singleton();
Singleton(const Singleton & rhs);
Singleton& operator=(const Singleton & rhs);
public:
static Singleton& getInstance()
{
Singleton * tmp = m_instance.load(std::memory_order_acquire);
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;
m_instance.store(tmp, std::memory_order_release);
}
}
return *tmp;
}
private:
static std::atomic<Singleton *> m_instance;
static std::mutex m_mutex;
};
goudan-er SHARE · CPP
C++