黃岡貼吧黃岡論壇吧今日頭條seo
多線程之單例模式
- 什么是設(shè)計(jì)模式,都有哪些設(shè)計(jì)模式
- 單例模式
- 餓漢模式
- 懶漢模式
什么是設(shè)計(jì)模式,都有哪些設(shè)計(jì)模式
設(shè)計(jì)模式就是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性、程序的重用性。
創(chuàng)建模式中:
抽象工廠模式 ,提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無需指定它們具體的類。
生成器模式,將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
工廠方法模式,定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定將哪一個(gè)類實(shí)例化。工廠方法使一個(gè)類的實(shí)例化延遲到其子類。
原型模式,用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過拷貝這個(gè)原型來創(chuàng)建新的對(duì)象。
單例模式,保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。
結(jié)構(gòu)模式中:
適配器模式,將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
橋接模式,將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。
組合模式,將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。它使得客戶對(duì)單個(gè)對(duì)象和復(fù)合對(duì)象的使用具有一致性。
容器模式
修飾模式,動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就擴(kuò)展功能而言, 它比生成子類方式更為靈活。 擴(kuò)展性模式 外觀模式
享元模式
管道與過濾器模式
代理模式,為其他對(duì)象提供一個(gè)代理以控制對(duì)這個(gè)對(duì)象的訪問。
行為模式中
責(zé)任鏈模式,為解除請(qǐng)求的發(fā)送者和接收者之間耦合,而使多個(gè)對(duì)象都有機(jī)會(huì)處理這個(gè)請(qǐng)求。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它。
命令模式,將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而使你可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可取消的操作。
單例模式
一個(gè)類只能創(chuàng)建一個(gè)對(duì)象,即單例模式,該模式可以保證系統(tǒng)中該類只有一個(gè)實(shí)例,并提供一個(gè) 訪問它的全局訪問點(diǎn),該實(shí)例被所有程序模塊共享,而單例模式有兩種實(shí)現(xiàn)模式:懶漢模式和餓漢模式
餓漢模式
這個(gè)單例類對(duì)象,在程序啟動(dòng)之初就直接創(chuàng)建(由于定義了一個(gè)靜態(tài)的類對(duì)象)
class Singleton{public:static Singleton* GetInstance(){return &m_instance;}private:// 構(gòu)造函數(shù)私有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;
優(yōu)點(diǎn):實(shí)現(xiàn)簡單,適用于多線程高并發(fā)環(huán)境下使用餓漢模式創(chuàng)建的單例類可以避免資源競(jìng)爭(zhēng)
缺點(diǎn):可能會(huì)導(dǎo)致進(jìn)程啟動(dòng)慢,如果有多個(gè)單例類對(duì)象啟動(dòng)時(shí)順序是不確定的
懶漢模式
這個(gè)單例對(duì)象,只有在程序被調(diào)用的時(shí)候,才去創(chuàng)建類的對(duì)象(根本原因是定義了一個(gè)靜態(tài)的類對(duì)象指針)
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;}// 實(shí)現(xiàn)一個(gè)內(nèi)嵌垃圾回收類 class CGarbo {public:~CGarbo(){if (Singleton::m_pInstance)delete Singleton::m_pInstance;}};// 定義一個(gè)靜態(tài)成員變量,程序結(jié)束時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用它的析構(gòu)函數(shù)從而釋放單例對(duì)象static CGarbo Garbo;private:// 構(gòu)造函數(shù)私有Singleton(){};// 防拷貝Singleton(Singleton const&);Singleton& operator=(Singleton const&);static Singleton* m_pInstance; // 單例對(duì)象指針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;
}
優(yōu)點(diǎn):第一次使用實(shí)例對(duì)象時(shí),才會(huì)創(chuàng)建對(duì)象,進(jìn)程啟動(dòng)無負(fù)載,多個(gè)單例實(shí)例啟動(dòng)順序自由控制
缺點(diǎn):復(fù)雜