C++单例模式:单例模式遇到多线程
單例模式介紹
單例模式主要有2中形式,一種是餓漢式,一種是懶漢式。
餓漢式:程序一加載單例模式就已經(jīng)創(chuàng)建了,也就很饑餓嘛。因?yàn)槭?span style="color:#ff0000">靜態(tài)屬性進(jìn)行單例初始化,所以優(yōu)點(diǎn)是線程是安全的,缺點(diǎn)是無(wú)論用戶是否使用單例對(duì)象都會(huì)創(chuàng)建單例對(duì)象。
懶漢式:當(dāng)用戶使用單例對(duì)象時(shí),才去創(chuàng)建單例對(duì)象,所以很懶惰嘛。優(yōu)點(diǎn)是用戶不使用就不會(huì)創(chuàng)建對(duì)象,缺點(diǎn)是 當(dāng)遇到多線程是,是線程不安全的,但是我們可以使用加強(qiáng)版的也就是線程安全的懶漢式,下面我們會(huì)進(jìn)行講解。
餓漢式和懶漢式代碼
代碼展示
#include <iostream>using namespace std; class Singleton_Hungry { private:Singleton_Hungry(){cout << "我是餓漢式,在程序加載時(shí),我就已經(jīng)存在了。" << endl;}static Singleton_Hungry* singleton; public:static Singleton_Hungry* getInstace(){return singleton;}}; //靜態(tài)屬性類外初始化 Singleton_Hungry* Singleton_Hungry::singleton = new Singleton_Hungry;class Singleton_Lazy { private:Singleton_Lazy(){cout << "我是懶漢式,在別人需要我的時(shí)候,我才現(xiàn)身。" << endl;}static Singleton_Lazy* singleton; public:static Singleton_Lazy* getInstance(){if (NULL == singleton){singleton = new Singleton_Lazy;}return singleton;} }; Singleton_Lazy* Singleton_Lazy::singleton = NULL;int main(int argc, char *argv[]) {Singleton_Hungry *hungry1 = Singleton_Hungry::getInstace();Singleton_Hungry *hungry2 = Singleton_Hungry::getInstace();cout << "hungry1地址:" << hungry1 << ",hungry2地址:" << hungry2 << endl;Singleton_Lazy *lazy1 = Singleton_Lazy::getInstance();Singleton_Lazy *lazy2 = Singleton_Lazy::getInstance();cout << "lazy1地址:" << lazy1 << ",lazy2地址:" << lazy1 << endl;return 0; }運(yùn)行結(jié)果
懶漢式遇到多線程
由于懶漢式在用戶需要是才進(jìn)行單例對(duì)象的創(chuàng)建,如果遇到多線程容易發(fā)生內(nèi)存泄漏,我們可以用c++中的線程互斥對(duì)象mutex來(lái)進(jìn)行加強(qiáng)。多線程用thread類進(jìn)模擬。
代碼展示
#include <iostream> #include <mutex> #include <thread>using namespace std; mutex mu;//線程互斥對(duì)象 class Singleton_Hungry { private:Singleton_Hungry(){cout << "我是餓漢式,在程序加載時(shí),我就已經(jīng)存在了。" << endl;}static Singleton_Hungry* singleton; public:static Singleton_Hungry* getInstace(){return singleton;}}; //靜態(tài)屬性類外初始化 Singleton_Hungry* Singleton_Hungry::singleton = new Singleton_Hungry;class Singleton_Lazy { private:Singleton_Lazy(){cout << "我是懶漢式,在別人需要我的時(shí)候,我才現(xiàn)身。" << endl;}static Singleton_Lazy* singleton; public:static Singleton_Lazy* getInstance(){if (NULL == singleton){mu.lock();//關(guān)閉鎖if (NULL == singleton){singleton = new Singleton_Lazy;}mu.unlock();//打開鎖}return singleton;} }; Singleton_Lazy* Singleton_Lazy::singleton = NULL; void thread01() {for (int i = 0; i < 5; i++){cout << "thread01 working...." << endl;Singleton_Lazy *lazy1 = Singleton_Lazy::getInstance();cout << "thread01創(chuàng)建單例lazy1地址:" << lazy1 << endl;} } void thread02() {for (int i = 0; i < 5; i++){cout << "thread02 working...." << endl;Singleton_Lazy *lazy2 = Singleton_Lazy::getInstance();cout << "thread02創(chuàng)建單例lazy2地址:" << lazy2 << endl;} }int main(int argc, char *argv[]) {thread thread1(thread01);thread thread2(thread01);thread1.detach();thread2.detach();for (int i = 0; i < 5; i++){cout << "Main thread working..." << endl;Singleton_Lazy *main = Singleton_Lazy::getInstance();cout << "Main 創(chuàng)建單例lazy地址:" << main << endl;}return 0; }
多線程下線程不安全的懶漢式測(cè)試
下圖是將40行45行線程互斥對(duì)象操作注釋的情況,發(fā)生了內(nèi)存泄漏,創(chuàng)建了多個(gè)單例。圖中字打錯(cuò)了。。。
多線程下線程安全的懶漢式測(cè)試
總結(jié)
以上是生活随笔為你收集整理的C++单例模式:单例模式遇到多线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 记一次性能调优
- 下一篇: Unable to instantiat