閑聊c/c++ 8: 設(shè)計模式: 單例模式真的簡單嗎?(上)

設(shè)計模式簡介:

設(shè)計模式描述了對象如何進(jìn)行通信才能不牽涉相互的數(shù)據(jù)模型和方法另绩。

保持這種獨(dú)立性一直是一個好的面向?qū)ο蟪绦蛟O(shè)計的目標(biāo)。 

Gang of Four的“Design Patterns: Elements of Resualbel Software”書將設(shè)計模式
歸納為三大類型,共23種些侍。

創(chuàng)建型模式 :  通常和對象的創(chuàng)建有關(guān)涝焙,涉及到對象實(shí)例化的方式垫言。(共5種模式)

行為型模式: 通常和對象間通信有關(guān)码耐。(共11種模式)

結(jié)構(gòu)型模式: 描述的是如何組合類和對象以獲得更大的結(jié)構(gòu)巍举。(共7種模式)
                          
            類模式描述的是如何使用繼承提供更有用的程序接口。

            而對象模式描述的是如何通過使用對象組合或?qū)ο蟀谄渌麑ο罄铮?            將對象組合成更大的一個結(jié)構(gòu)蛋逾。

單例模式的適用范圍:

1集晚、單例模式可以保證:在一個應(yīng)用程序中,一個類有且只有一個實(shí)例区匣,
 并提供一個訪問它的全局訪問點(diǎn)偷拔。

2、在程序設(shè)計過程中亏钩,有很多情況需要確保一個類只有一個實(shí)例条摸。
 例如:
          windows系統(tǒng)中只能有一個窗口管理器

          某個程序中只能有一個日志輸出系統(tǒng)

          一個GUI類庫中,有且只有一個ImageManager

          還有其他無數(shù)種情況

教科書中的標(biāo)準(zhǔn)實(shí)現(xiàn):

教科書實(shí)現(xiàn).png

教課書中的標(biāo)準(zhǔn)實(shí)現(xiàn)的優(yōu)缺點(diǎn):

1铸屉、優(yōu)點(diǎn):該實(shí)現(xiàn)是一個"懶漢"單例模式,意味著只有在第一次調(diào)用GetInstance()切端,靜  態(tài)方法的時候才進(jìn)行內(nèi)存分配彻坛。如果整個程序不調(diào)用該靜態(tài)方法,則不會分配內(nèi)存踏枣。相對應(yīng)的是"餓漢"單例模式昌屉。

2、缺點(diǎn):  1) "懶漢"模式雖然有優(yōu)點(diǎn)茵瀑,但是每次調(diào)用GetInstance()靜態(tài)方法時间驮,
              必須判斷NULL == m_instance,使程序相對開銷增大马昨。

           2) 由于使用指針動態(tài)內(nèi)存分配竞帽,我們必須在程序結(jié)束時,
              手動的調(diào)用ReleaseInstance()靜態(tài)方法鸿捧,進(jìn)行內(nèi)存的釋放屹篓。

           3) 教科書標(biāo)準(zhǔn)實(shí)現(xiàn)最大的缺點(diǎn)是線程不安全。
              根據(jù)該模式的定義匙奴,整個應(yīng)用程序中堆巧,不管是單線程,還是多線程,
              都只能有且只有該類的一個實(shí)例谍肤。而在多線程中會導(dǎo)致多個實(shí)例的產(chǎn)生啦租,                 
              從而導(dǎo)致運(yùn)行代碼不正確以及內(nèi)存的泄露。

教課書中的標(biāo)準(zhǔn)實(shí)現(xiàn)的線程不安全性演示:

線程不安全性演示代碼.png
VS2008線程不安全行演示效果.png
VS2015線程不安全演示效果.png
1荒揣、我們創(chuàng)建3個輔助線程篷角,外加main主線程,一共有4個線程乳附。

2内地、我們在每個輔助線程里面調(diào)用GetInstance()靜態(tài)方法,由于每個線程
  回調(diào)函數(shù)速度非掣吵快阱缓,導(dǎo)致每個線程在判斷NULL==m_instance時,
  都返回true,從而導(dǎo)致每個線程回調(diào)函數(shù)都會創(chuàng)建一個CSingleton1對
  象并返回指向該對象的指針举农。

3荆针、我們根本沒辦法進(jìn)行CSingleton1的內(nèi)存釋放,因為在多線程中颁糟,
   我們根本不知道是創(chuàng)建了1個航背、2個或3個CSingleton1的實(shí)例

Meyers Singleton Pattern實(shí)現(xiàn):

Meyers Singleton.png

Meyers Singleton Pattern的優(yōu)缺點(diǎn) :

1、優(yōu)點(diǎn):
           1)  該實(shí)現(xiàn)是一個"懶漢"單例模式棱貌,意味著只有在第一次調(diào)用GetInstance()時才會
                實(shí)例化玖媚。

           2)  不需要每次調(diào)用GetInstance()靜態(tài)方法時,必須判斷NULL==m_instance,效
                 率相對高一些婚脱。

           3)  使用對象而不是指針分配內(nèi)存今魔,因此自動回調(diào)用析構(gòu)函數(shù),不會導(dǎo)致內(nèi)存泄露障贸。

           4)  在多線程下的確能夠保證有且只有一個實(shí)例產(chǎn)生错森。
           

2、缺點(diǎn):

          在某些編譯器中篮洁,在多線程情況下涩维,并不是真正意義上的線程安全的實(shí)現(xiàn)

Meyers Singleton Pattern缺點(diǎn)演示:

我們修改一下前面線程函數(shù)

Instance2測試.png
VS2008Meyers單例線程不安全性演示.png

Meyers Singleton Pattern線程不安全性的原因:

    這是因為C++中構(gòu)造函數(shù)并不是線程安全的。

    C++中的構(gòu)造函數(shù)簡單來說分兩步:

    第一步:內(nèi)存分配

    第二步:初始化成員變量

    由于多線程的關(guān)系袁波,可能當(dāng)我們在分配內(nèi)存好了以后瓦阐,還沒來得急初始化成員變量,就
    進(jìn)行線程切換锋叨,另外一個線程拿到所有權(quán)后垄分,由于內(nèi)存已經(jīng)分配了,但是變量初始化還
    沒進(jìn)行娃磺,因此打印成員變量的相關(guān)值會發(fā)生不一致現(xiàn)象薄湿。

    結(jié)論:Meyers方式雖然能確保在多線程中產(chǎn)生唯一的實(shí)例,但是不能確保成員變量的值是否正確.

Next:
下一篇我們來實(shí)現(xiàn)一個線程安全,無內(nèi)存泄漏豺瘤,基于“懶漢”行為的單例模式吆倦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坐求,隨后出現(xiàn)的幾起案子蚕泽,更是在濱河造成了極大的恐慌,老刑警劉巖桥嗤,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件须妻,死亡現(xiàn)場離奇詭異,居然都是意外死亡泛领,警方通過查閱死者的電腦和手機(jī)荒吏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渊鞋,“玉大人绰更,你說我怎么就攤上這事∥危” “怎么了儡湾?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長执俩。 經(jīng)常有香客問我徐钠,道長,這世上最難降的妖魔是什么役首? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任丹皱,我火速辦了婚禮,結(jié)果婚禮上宋税,老公的妹妹穿的比我還像新娘。我一直安慰自己讼油,他們只是感情好杰赛,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矮台,像睡著了一般乏屯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘦赫,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天辰晕,我揣著相機(jī)與錄音,去河邊找鬼确虱。 笑死含友,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窘问,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼辆童,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惠赫?” 一聲冷哼從身側(cè)響起把鉴,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎儿咱,沒想到半個月后庭砍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡混埠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年怠缸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岔冀。...
    茶點(diǎn)故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡凯旭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出使套,到底是詐尸還是另有隱情罐呼,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布侦高,位于F島的核電站嫉柴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏奉呛。R本人自食惡果不足惜计螺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瞧壮。 院中可真熱鬧登馒,春花似錦、人聲如沸咆槽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秦忿。三九已至麦射,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間灯谣,已是汗流浹背潜秋。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胎许,地道東北人峻呛。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓罗售,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杀饵。 傳聞我的和親對象是個殘疾皇子莽囤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容