單例模式:安全
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。函數
特色:spa
一、私有的構造函數線程
二、私有的複製構造函數code
三、私有的賦值操做符blog
問題:內存
一、線程安全資源
二、數據的清理get
代碼:class
通常有三種寫法:
方法一:一個不是線程安全的代碼,並且也沒有解決內存釋放的問題:
1 class Singleton 2 { 3 public: 4 static Singleton* getInstance() 5 { 6 7 /**< 假若有兩個線程,第一個線程運行時,判斷pInstance是否爲空,由於此時pInstance 8 * ==NULL,那麼線程將會進入到if結構體內,假設,就在要執行new Singleton這個操做 9 * 時,時間片結束,那麼此時pInstance仍是爲NULL,此時另外一個線程運行,當它進行判 10 * 斷時發現pInstance爲空,因此會建立一次,當它執行完後,第一個線程執行,又會產 11 * 生一個新的實例,那麼將會產生兩個,因此此時是線程不安全的。要想保證安全,必須 12 * if前面加鎖 13 */ 14 if(pInstance == NULL) 15 { 16 pInstance = new Singleton; 17 } 18 return pInstance; 19 }; 20 private: 21 Singleton(){}; 22 Singleton(const Singleton &); 23 Singleton& operator=(const Singleton &); 24 25 static Singleton *pInstance; 26 }; 27 28 Singleton* Singleton::pInstance = NULL;
方法二 :只解決了內存釋放的問題:
1 class Singleton 2 { 3 public: 4 static Singleton* getInstance() 5 { 6 /**< 其實這裏加上互斥操做,就能夠實現,便是線程安全,又釋放了內存 */ 7 if(pInstance == NULL) 8 { 9 pInstance = new Singleton; 10 } 11 return pInstance; 12 }; 13 14 class Garbage 15 { 16 public: 17 ~Garbage() 18 { 19 if(Singleton::pInstance) 20 { 21 delete pInstance; 22 } 23 }; 24 }; 25 private: 26 Singleton(){}; 27 Singleton(const Singleton &); 28 Singleton& operator=(const Singleton &); 29 30 static Singleton *pInstance; 31 static Garbage m_Garbage; /**< 當這個靜態變量釋放時,會自動去釋放Singleton的資源*/ 32 };
方法三:即解決了線程安全的問題,也解決了內存釋放的問題
1 class Singleton 2 { 3 public: 4 static Singleton* getInstance() 5 { 6 /**< 此函數會在全局區中分配空間,並且在整個程序退出時,清理數據 7 * ,因此就不會存在線程不安全的狀況 8 */ 9 static Singleton single; 10 return &single; 11 }; 12 private: 13 Singleton(){}; 14 Singleton(const Singleton &); 15 Singleton& operator=(const Singleton &); 16 };