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++