• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            西城

            指尖代碼,手上年華

            聯系 聚合 管理
              20 Posts :: 0 Stories :: 62 Comments :: 0 Trackbacks
            在看POCO網絡庫的時候,其中實現了一個singleton模式,提到了DCLP的不可行性。就去查閱了一下,
            找到了這篇文章。原文太長,將其意思大略整理如下。

            singleton差不多是所有設計模式中最為常見的一個,但卻不是線程安全的。
            DCLP就是為了消除此缺點而設計出來的——Double Checked Locking Pattern。但卻仍然是
            不可靠的。


            一般的singleton實現為:
            // from the header file
            class Singleton {
            public:
            static Singleton* instance();

            private:
            static Singleton* pInstance;
            };
            // from the implementation file
            Singleton* Singleton::pInstance = 0;
            Singleton* Singleton::instance() {
            if (pInstance == 0) {                //Line 1
               pInstance=new Singleton;         //Line 2
            }
            return pInstance;
            }
            單線程模式下,這種方法工作的很好。但在多線程模式下卻是有問題的。
            假設線程A進入了instance函數,執行到Line 1,然后被掛起。當它被掛起的時候,它
            剛測得pInstance是NULL,所以還沒有Singleton對象被創造出來。
            然后線程B進入instance并且執行到line1,發現pInstance是NULL,然后執行下一句,創建了一個
            Singleton并且使pInstance指向它。然后返回pInstance.
            當線程A繼續執行的時候,它會執行Line2,創建一個Singleton并使pInstance指向它,這就
            破壞了singleton的意義,因為創建了兩個singleton.
            要想使其是線程安全的,需要在測試pInstance之間加一個lock.
            Singleton* Singleton::instance() {
            Lock lock;
            // acquire lock (params omitted for simplicity)
            if (pInstance == 0) {
            pInstance = new Singleton;
            }
            return pInstance;
            }
            // release lock 

            這樣有一個和很大的缺點——代價太高,每次訪問都需要一個lock.但實際上,我們只需要在
            第一次創建的時候加一個鎖,而且應該是instance第一次被調用的時候。如果在運行時
            instance被調用了n次,我們只需要在第一次調用的時候加鎖就可以了。DCLP就是為了
            解決這個問題而設計的--------------去掉那些不必要的LOCK。
            Singleton* Singleton::instance() {
            if (pInstance == 0) {
            // 1st test
            Lock lock;
            if (pInstance == 0) {
            // 2nd test
            pInstance = new Singleton;
            }
            }
            return pInstance;
            }
            DCLP在加鎖之前先測試pInstance是否為空,盡在其為NULL時才會需要一個LOCK,第二次測試也是
            必要的,因為有可能另一個線程在第一次測試pInstance和請求LOCK時執行了new.

            問題之所在:
            pInstance=new Singleton;分為以下三步:
            1.分配內存(sizeof(Singleton).
            2.在分配的內存上創建一個Singleton對象。
            3.讓pInstance指向這塊內存。問題就在于編譯器不一定按照順序執行這三步。 有時候編譯器會將
            第二步和第三步互換。此時情況可能如以下所示:
            Singleton* Singleton::instance() {
            if (pInstance == 0) {
            Lock lock;
            if (pInstance == 0) {
            pInstance =
            // Step 3
            operator new(sizeof(Singleton)); // Step 1
            // Step 2
            new (pInstance) Singleton;
            }
            }
            return pInstance;
            }
            在實際的DCLP代碼中,step2是可能拋出異常的,這時需要保證pInstance沒有變化(setp3未
            執行)。所以一般并不能把step3移到step2之前,但有時候是可以的,比如說step2并不拋出異
            常。
            現在如果線程A進入instance,進行第一次測試,請求了一個LOCK,然后執行了step1和step3.
            然后被掛起。此時pInstance是NO-NULL,但是沒有singleton對象被創建出來。
            然后,線程B進入instance,發現pInstance非空,然后將其返回,然后解引用,但是卻沒有對象。
            所以,DCLP只有在step1和step2在step3之前完成的情況下才能正常工作,但C/C++并不提供這樣的
            保證。
            posted on 2012-04-20 20:20 西城 閱讀(6796) 評論(7)  編輯 收藏 引用 所屬分類: C/C++

            Feedback

            # re: 為什么DCLP是不可行的?(1) 2012-04-21 10:36 runner.mei
            說了半天,無非是想法要為 pInstance 加上 violate 修飾符嘛, 最新的 vc++ 和 gcc 都擴展了 violate 的語義, 保證了它的原子性(Atomicity)和順序性(Ordering)了。DCLP是可行的  回復  更多評論
              

            # re: 為什么DCLP是不可行的?(1) 2012-04-21 10:39 runner.mei
            說了半天,無非是想說要為 pInstance 加上 violate 修飾符嘛, 最新的 vc++ 和 gcc 都擴展了 violate 的語義, 保證了它的原子性(Atomicity)和順序性(Ordering)了。DCLP是可行的。
            已經不是原創了,還分成幾篇,賺點擊。  回復  更多評論
              

            # re: 為什么DCLP是不可行的?(1) 2013-03-15 11:32 Eric.Tsai

            pInstance = new Singleton;
            改成
            Singleton *pTemp = new Singleton;
            pInstance = pTemp;
            不就可以避免了嗎? 還是我理解不夠透徹?  回復  更多評論
              

            # re: 為什么DCLP是不可行的?(1) 2013-03-15 11:44 Eric.Tsai
            看了原文才知道忘記"編譯器優化了"@Eric.Tsai
              回復  更多評論
              

            国产高清国内精品福利99久久| 色婷婷久久综合中文久久蜜桃av| 97久久综合精品久久久综合| 国产成人久久精品一区二区三区 | 国产三级久久久精品麻豆三级| 狠狠色丁香婷婷久久综合五月| 久久精品国产亚洲av麻豆蜜芽| 久久99精品久久只有精品| 久久久无码一区二区三区 | 国产高清国内精品福利99久久| 人妻无码久久精品| 久久亚洲AV无码精品色午夜麻豆 | 狠狠色丁香久久婷婷综合| 国内精品综合久久久40p| 色婷婷综合久久久久中文| 人人狠狠综合久久亚洲| 国产亚洲美女精品久久久久狼| 久久无码专区国产精品发布| 久久丫精品国产亚洲av不卡| 亚洲精品高清一二区久久| 国产精品久久久久国产A级| 超级97碰碰碰碰久久久久最新| 国产综合精品久久亚洲| 婷婷久久久亚洲欧洲日产国码AV | 久久综合九色综合久99| 久久综合九色欧美综合狠狠| 亚洲综合久久综合激情久久| 亚洲精品无码久久久久| 亚洲午夜福利精品久久| 免费一级做a爰片久久毛片潮| 激情久久久久久久久久| 精品一区二区久久| 伊人久久大香线焦AV综合影院| 久久人妻少妇嫩草AV蜜桃| 94久久国产乱子伦精品免费 | 久久夜色精品国产噜噜噜亚洲AV| 久久亚洲高清综合| 日韩亚洲国产综合久久久| 欧美大战日韩91综合一区婷婷久久青草| 狠狠狠色丁香婷婷综合久久五月| 久久久久久亚洲精品成人|