-
概念
- 程序的生命週期內只有一個實例的存在
-
場景
- 日誌記錄器、數據庫連接池、線程池等
-
實現
#include <iostream> #include <mutex> #include <boost/noncopyable.hpp> using namespace std; // 版本一 // 創建即初始化-eager initialize // 不過需要提前初始化。但是從生產環境考慮,單例模式必須創建,同時需要系統預熱。 // 因此該版本也具有一定的適用性。 class Singleton : public boost::noncopyable{ private: shared_ptr<Singleton> sp_instance; private: Singleton() = default; public: // 智能指針的析構函數需要對象的析構函數的訪問權限 ~Singleton() = default; static weak_ptr<Singleton> GetInstance() { return sp_instance; } }; shared_ptr<Singleton> Singleton::sp_instance(new Singleton);#include <iostream> #include <mutex> #include <boost/noncopyable.hpp> using namespace std; // 以下幾個版本為用時創建,Lazy模式。 // 版本二 // 會出現寫放大(A進程創建智能指針A並賦值給靜態單例變量, // 此時發生進程切換,B進程創建智能指針B並賦值給單例變量,因此A進程創建的智能指針A自動銷燬)。 // 總的來説,能夠正確創建並返回對象,但是初始會多創建一次浪費資源 class Singleton : public boost::noncopyable{ private: Singleton() = default; public: // 智能指針需要調用 ~Singleton() = default; static weak_ptr<Singleton> GetInstance() { static shared_ptr<Singleton> sp_singleton = shared_ptr<Singleton> (new Singleton()); return sp_singleton; } };// 版本三 // 先上鎖->併發退化成串行。 // 在寫-讀場景下併發能力弱。適用於寫-寫場景。 class Singleton : public boost::noncopyable{ private: shared_ptr<Singleton> sp_instance; mutex_t mutex; private: Singleton() = default; public: // 智能指針需要調用 ~Singleton() = default; static weak_ptr<Singleton> GetInstance() { mutex.lock(); // RALL if (sp_instance == nullptr) sp_instance = shared_ptr<Singleton> (new Singleton()); return sp_singleton; } };// 版本四 // DCL+volatile關鍵字->版本三的優化。 // 通過volatile關鍵字防止最外層判斷出現未完全初始化對象,通過內層加鎖保證過程的互斥性。 // 適合寫-讀場景。 class Singleton : public boost::noncopyable{ private: static volatile shared_ptr<Singleton> instance; static std::mutex mutex; private: Singleton() = default; public: ~Singleton() {} static weak_ptr<Singleton> GetInstance() { if (instance == nullptr) { mutex.lock(); if (instance == nullptr) { instance = shared_ptr<Singleton> (new Singleton()); } } return instance; } }; int main() { auto ptr_singleton = Singleton::GetInstance(); // do something... }