多線程之單例模式
- 什么是設計模式,都有哪些設計模式
- 單例模式
- 餓漢模式
- 懶漢模式
什么是設計模式,都有哪些設計模式
設計模式就是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性、程序的重用性。
創建模式中:
抽象工廠模式 ,提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
生成器模式,將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
工廠方法模式,定義一個用于創建對象的接口,讓子類決定將哪一個類實例化。工廠方法使一個類的實例化延遲到其子類。
原型模式,用原型實例指定創建對象的種類,并且通過拷貝這個原型來創建新的對象。
單例模式,保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
結構模式中:
適配器模式,將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
橋接模式,將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
組合模式,將對象組合成樹形結構以表示“部分-整體”的層次結構。它使得客戶對單個對象和復合對象的使用具有一致性。
容器模式
修飾模式,動態地給一個對象添加一些額外的職責。就擴展功能而言, 它比生成子類方式更為靈活。 擴展性模式 外觀模式
享元模式
管道與過濾器模式
代理模式,為其他對象提供一個代理以控制對這個對象的訪問。
行為模式中
責任鏈模式,為解除請求的發送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它。
命令模式,將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可取消的操作。
單例模式
一個類只能創建一個對象,即單例模式,該模式可以保證系統中該類只有一個實例,并提供一個 訪問它的全局訪問點,該實例被所有程序模塊共享,而單例模式有兩種實現模式:懶漢模式和餓漢模式
餓漢模式
這個單例類對象,在程序啟動之初就直接創建(由于定義了一個靜態的類對象)
class Singleton{public:static Singleton* GetInstance(){return &m_instance;}private:// 構造函數私有Singleton(){};// C++98 防拷貝Singleton(Singleton const&); Singleton& operator=(Singleton const&); // or// C++11Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton m_instance;};Singleton Singleton::m_instance;
優點:實現簡單,適用于多線程高并發環境下使用餓漢模式創建的單例類可以避免資源競爭
缺點:可能會導致進程啟動慢,如果有多個單例類對象啟動時順序是不確定的
懶漢模式
這個單例對象,只有在程序被調用的時候,才去創建類的對象(根本原因是定義了一個靜態的類對象指針)
class Singleton
{public:static Singleton* GetInstance() {// 注意這里一定要使用Double-Check的方式加鎖,才能保證效率和線程安全if (nullptr == m_pInstance) {m_mtx.lock();if (nullptr == m_pInstance) {m_pInstance = new Singleton();}m_mtx.unlock();}return m_pInstance;}// 實現一個內嵌垃圾回收類 class CGarbo {public:~CGarbo(){if (Singleton::m_pInstance)delete Singleton::m_pInstance;}};// 定義一個靜態成員變量,程序結束時,系統會自動調用它的析構函數從而釋放單例對象static CGarbo Garbo;private:// 構造函數私有Singleton(){};// 防拷貝Singleton(Singleton const&);Singleton& operator=(Singleton const&);static Singleton* m_pInstance; // 單例對象指針static mutex m_mtx; //互斥鎖
};
Singleton* Singleton::m_pInstance = nullptr;
Singleton::CGarbo Garbo;
mutex Singleton::m_mtx;
int main()
{thread t1([]{cout << &Singleton::GetInstance() << endl; });thread t2([]{cout << &Singleton::GetInstance() << endl; });t1.join();t2.join();cout << &Singleton::GetInstance() << endl;cout << &Singleton::GetInstance() << endl;return 0;
}
優點:第一次使用實例對象時,才會創建對象,進程啟動無負載,多個單例實例啟動順序自由控制
缺點:復雜