Stories

Detail Return Return

單例模式+線程安全 - Stories Detail

  • 概念

    • 程序的生命週期內只有一個實例的存在
  • 場景

    • 日誌記錄器、數據庫連接池、線程池等
  • 實現

    #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...
    }

Add a new Comments

Some HTML is okay.