程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 單例模式全面學習(C++版)

單例模式全面學習(C++版)

編輯:C++入門知識

單例模式全面學習(C++版)


單例模式:用來創建獨一無二的,只能夠有一個實例的對象。 單例模式的結構是設計模式中最簡單的,但是想要完全實現一個線程安全的單例模式還是有很多陷阱的,所以面試的時候屬於一個常見的考點~   單例模式的應用場景:有一些對象其實只需要一個,比如:線程池,緩存,對話框,處理偏好設置和注冊表的對象,日志對象,充當打印機,顯卡等設備的驅動程序對象。這些對象只能夠擁有一個實例,如果創建出了多個實例,就會導致一些程序的問題。程序的行為異常,資源使用的過量,或者導致不一致的結果。常用來管理共享的資源,比如數據庫的連接或者線程池。   單例模式的類圖非常簡單,如下~,並且經典的實現也非常的簡單。         class Singleton { public:     static Singleton* getInstance();     //析構的時候釋放資源~     ~Singleton() {         if( (_instance != NULL)              delete _instance;     } protected:     Singleton(); private:     static Singleton* _instance; }   Singleton *Singleton::_instance = NULL; Singleton* Singleton::getInstance() {     if( _instance == NULL) {         _instance = new Singleton();     }     return _instance; }    經典的實現非常容易,但是存在一個問題,就是這個經典的實現非線程安全,多線程的情況下,這個單例模式的實現會出現問題~,如何解決呢?改進!      class Lock { private:            mutex mtex; public:     Lock(mutex m) : mtex(m)     {         mtex.Lock();     }     ~Lock()     {         mtex.Unlock();     } };   class Singleton { public:     static Singleton* getInstance();     //析構的時候釋放資源~     ~Singleton() {         if( (_instance != NULL)              delete _instance;     } protected:     Singleton(); private:     static Singleton* _instance;<br>    static mutex m; }   Singleton *Singleton::_instance = NULL; Singleton* Singleton::getInstance() {<br>    //check 之前進行臨界區加鎖操作<br>    Lock lock(m);     if( _instance == NULL) {         _instance = new Singleton();     }     return _instance; } 線程安全保證的一種方法及為在check _instance == NULL 之前進行臨界區加鎖,如果已經有一個線程進入訪問,其他線程必須等待,這樣就能夠保證多線程情況下實例的唯一!   but,互斥的同步會導致性能的降低,即使_instance已經不為空了,每次還是需要加鎖,這樣操作花費就比較多,性能必定比較差。   另外還有一些比較好的方法:   1.(非線程同步的方法)上面的操作均為一種lazy initialization的思想,及用到的時候在初始化,這樣程序效率比較高,但是有一個另外比較好的方法可以采用是提前初始化,將_instance設置為static之後直接初始化為Singleton對象,每次只需要執行返回操作即可。   這樣的話同樣會導致問題,就是如果單例本來資源比較多,但是不需要創建那麼早,就會消耗資源~。   class Singleton { public:     static Singleton* getInstance();     //析構的時候釋放資源~     ~Singleton() {             delete _instance;     } protected:     Singleton(); private:     static Singleton* _instance; }   Singleton *Singleton::_instance = new Singleton(); Singleton* Singleton::getInstance() {     return _instance; } 2.另外一種提升因為同步導致的性能變差的方法稱為“雙重檢驗加鎖”。方法如下:   思路是只有在第一次創建的時候進行加鎖,當_instance不為空的時候就不需要進行加鎖的操作,這樣就可以提升性能~   class Lock { private:            mutex mtex; public:     Lock(mutex m) : mtex(m)     {         mtex.Lock();     }     ~Lock()     {         mtex.Unlock();     } }; class Singleton { public:     static Singleton* getInstance();     //析構的時候釋放資源~     ~Singleton() {         if( (_instance != NULL)              delete _instance;     } protected:     Singleton(); private:     static Singleton* _instance;     static mutex m; }   Singleton *Singleton::_instance = NULL; Singleton* Singleton::getInstance() {     //check 之前進行臨界區加鎖操作     //雙重檢驗加鎖     if(_instance == NULL ) {         Lock lock(m);         if( _instance == NULL) {             _instance = new Singleton();         }     }     return _instance; }     總之,小小單例模式問題還是挺多的,面試官喜歡問的一個問題~,因為還是有很多陷阱的。     

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved