老生常談C++的單例模式與線(xiàn)程安全單例模式(懶漢/餓漢)
1 教科書(shū)里的單例模式
我們都很清楚一個(gè)簡(jiǎn)單的單例模式該怎樣去實(shí)現(xiàn):構(gòu)造函數(shù)聲明為private或protect防止被外部函數(shù)實(shí)例化,內(nèi)部保存一個(gè)private static的類(lèi)指針保存唯一的實(shí)例,實(shí)例的動(dòng)作由一個(gè)public的類(lèi)方法代勞,該方法也返回單例類(lèi)唯一的實(shí)例。
上代碼:
class singleton { protected: singleton(){} private: static singleton* p; public: static singleton* instance(); }; singleton* singleton::p = NULL; singleton* singleton::instance() { if (p == NULL) p = new singleton(); return p; }
這是一個(gè)很棒的實(shí)現(xiàn),簡(jiǎn)單易懂。但這是一個(gè)完美的實(shí)現(xiàn)嗎?不!該方法是線(xiàn)程不安全的,考慮兩個(gè)線(xiàn)程同時(shí)首次調(diào)用instance方法且同時(shí)檢測(cè)到p是NULL值,則兩個(gè)線(xiàn)程會(huì)同時(shí)構(gòu)造一個(gè)實(shí)例給p,這是嚴(yán)重的錯(cuò)誤!同時(shí),這也不是單例的唯一實(shí)現(xiàn)!
2 懶漢與餓漢
單例大約有兩種實(shí)現(xiàn)方法:懶漢與餓漢。
懶漢:故名思義,不到萬(wàn)不得已就不會(huì)去實(shí)例化類(lèi),也就是說(shuō)在第一次用到類(lèi)實(shí)例的時(shí)候才會(huì)去實(shí)例化,所以上邊的經(jīng)典方法被歸為懶漢實(shí)現(xiàn);
餓漢:餓了肯定要饑不擇食。所以在單例類(lèi)定義的時(shí)候就進(jìn)行實(shí)例化。
特點(diǎn)與選擇:
由于要進(jìn)行線(xiàn)程同步,所以在訪(fǎng)問(wèn)量比較大,或者可能訪(fǎng)問(wèn)的線(xiàn)程比較多時(shí),采用餓漢實(shí)現(xiàn),可以實(shí)現(xiàn)更好的性能。這是以空間換時(shí)間。
在訪(fǎng)問(wèn)量較小時(shí),采用懶漢實(shí)現(xiàn)。這是以時(shí)間換空間。
3 線(xiàn)程安全的懶漢實(shí)現(xiàn)
線(xiàn)程不安全,怎么辦呢?最直觀的方法:加鎖。
方法1:加鎖的經(jīng)典懶漢實(shí)現(xiàn):
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } private: static singleton* p; public: static pthread_mutex_t mutex; static singleton* initance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::p = NULL; singleton* singleton::initance() { if (p == NULL) { pthread_mutex_lock(&mutex); if (p == NULL) p = new singleton(); pthread_mutex_unlock(&mutex); } return p; }
方法2:內(nèi)部靜態(tài)變量的懶漢實(shí)現(xiàn)
此方法也很容易實(shí)現(xiàn),在instance函數(shù)里定義一個(gè)靜態(tài)的實(shí)例,也可以保證擁有唯一實(shí)例,在返回時(shí)只需要返回其指針就可以了。推薦這種實(shí)現(xiàn)方法,真得非常簡(jiǎn)單。
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } public: static pthread_mutex_t mutex; static singleton* initance(); int a; }; pthread_mutex_t singleton::mutex; singleton* singleton::initance() { pthread_mutex_lock(&mutex); static singleton obj; pthread_mutex_unlock(&mutex); return &obj; }
4 餓漢實(shí)現(xiàn)
為什么我不講“線(xiàn)程安全的餓漢實(shí)現(xiàn)”?因?yàn)轲I漢實(shí)現(xiàn)本來(lái)就是線(xiàn)程安全的,不用加鎖。為啥?自己想!
class singleton { protected: singleton() {} private: static singleton* p; public: static singleton* initance(); }; singleton* singleton::p = new singleton; singleton* singleton::initance() { return p; }
是不是特別簡(jiǎn)單呢?
以空間換時(shí)間,你說(shuō)簡(jiǎn)單不簡(jiǎn)單?
面試的時(shí)候,線(xiàn)程安全的單例模式怎么寫(xiě)?肯定怎么簡(jiǎn)單怎么寫(xiě)呀!餓漢模式反而最懶[正經(jīng)臉]!
以上就是小編為大家?guī)?lái)的老生常談C++的單例模式與線(xiàn)程安全單例模式(懶漢/餓漢)全部?jī)?nèi)容了,希望大家多多支持我們~
上一篇:利用C++實(shí)現(xiàn)最長(zhǎng)公共子序列與最長(zhǎng)公共子串
欄 目:C語(yǔ)言
下一篇:C#如何調(diào)用原生C++ COM對(duì)象詳解
本文標(biāo)題:老生常談C++的單例模式與線(xiàn)程安全單例模式(懶漢/餓漢)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/1938.html
您可能感興趣的文章
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)式函數(shù)庫(kù)
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)數(shù)怎么表達(dá)
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎么打出三角函數(shù)的值
- 01-10c語(yǔ)言求1+2+...+n的解決方法
- 01-10求子數(shù)組最大和的解決方法詳解
- 01-10深入理解約瑟夫環(huán)的數(shù)學(xué)優(yōu)化方法
- 01-10深入二叉樹(shù)兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)- 解析最少換車(chē)次數(shù)的問(wèn)題詳解
- 01-10c語(yǔ)言 跳臺(tái)階問(wèn)題的解決方法


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?