我的java天地

          單例模式的一些版本及演變過程

          @import url(http://www.aygfsteel.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); @import url(http://www.aygfsteel.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); @import url(http://www.aygfsteel.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
          版本一:只支持單線程,多線程第一次實(shí)例化會(huì)有兩個(gè)實(shí)例生成
          class Foo {
          private Helper helper = null;
          public Helper getHelper() {
          if (helper == null)
          helper
          = new Helper();
          return helper;
          }
          // other functions and members...
          } 版本二:多線程版本:每個(gè)線程過來都會(huì)到要到synchronized 方法塊,這樣處理效率較低.第一個(gè)初始化helper的時(shí)候需要locking(加鎖),而后面取用helper的時(shí)候,根本不需要線程同步
          // Correct multithreaded version
          class Foo {
          private Helper helper = null;
          public synchronized Helper getHelper() {
          if (helper == null)
          helper
          = new Helper();
          return helper;
          }
          // other functions and members...
          } 版本三:解決每次新建實(shí)例都要
          synchronized的問題,運(yùn)用雙檢鎖來實(shí)現(xiàn).此種方法行不通
          class Foo {
          private Helper helper = null;
          public Helper getHelper() {
          if (helper == null)
          synchronized(
          this) {
          if (helper == null)
          helper
          = new Helper();
          }
          return helper;
          }
          // other functions and members...
          }
          思路很簡(jiǎn)單,就是我們只需要同步(synchronize)初始化helper的那部分代碼從而使代碼既正確又很有效率。

          這就是所謂的“雙檢鎖”機(jī)制(顧名思義)。

          很可惜,這樣的寫法在很多平臺(tái)和優(yōu)化編譯器上是錯(cuò)誤的。

          原因在于:helper = new Helper()這行代碼在不同編譯器上的行為是無法預(yù)知的。一個(gè)優(yōu)化編譯器可以合法地如下實(shí)現(xiàn)helper = new Helper():

          1. helper = 給新的實(shí)體分配內(nèi)存

          2. 調(diào)用helper的構(gòu)造函數(shù)來初始化helper的成員變量

          現(xiàn)在想象一下有線程A和B在調(diào)用getHelper,線程A先進(jìn)入,在執(zhí)行到步驟1的時(shí)候被踢出了cpu。然后線程B進(jìn)入,B看到的是 helper已經(jīng)不是null了(內(nèi)存已經(jīng)分配),于是它開始放心地使用helper,但這個(gè)是錯(cuò)誤的,因?yàn)樵谶@一時(shí)刻,helper的成員變量還都是缺 省值,A還沒有來得及執(zhí)行步驟2來完成helper的初始化。

          當(dāng)然編譯器也可以這樣實(shí)現(xiàn):

          1. temp = 分配內(nèi)存

          2. 調(diào)用temp的構(gòu)造函數(shù)

          3. helper = temp

          如果編譯器的行為是這樣的話我們似乎就沒有問題了,但事實(shí)卻不是那么簡(jiǎn)單,因?yàn)槲覀儫o法知道某個(gè)編譯器具體是怎么做的,因?yàn)樵贘ava的 memory model里對(duì)這個(gè)問題沒有定義(C++也一樣),而事實(shí)上有很多編譯器都是用第一種方法(比如symantec的just-in-time compiler),因?yàn)榈谝环N方法看起來更自然。

          在上面的參考文章中還提到了更復(fù)雜的修改方法,不過很可惜,都是錯(cuò)誤的

          關(guān)于Out-of-order writes現(xiàn)象,就是
          helper = new Helper();;
          helper已經(jīng)非空,但對(duì)象還沒完成實(shí)例化,即new new Helper()未完成
          詳見:
          http://www.ibm.com/developerworks/java/library/j-dcl.html


          版本四:目前知道最后版。實(shí)際應(yīng)用時(shí)需驗(yàn)證一下
          private volatile static Singleton instance;  
            
          public static Singleton getInstance() {  
              if (instance == null) {  
                  synchronized(Singleton.class) {  //1  
                      if (instance == null)          //2  
                          instance = new Singleton();  //3  
                  }  
              }  
              return instance;  
          }  

          因?yàn)榇嬖贠ut-of-order writes現(xiàn)象,所以這里volatile關(guān)鍵字是在當(dāng)instance被初始化給Singleton實(shí)例時(shí)保證多線程正確地處理instance變量,那這里與線程間的可見性有關(guān)嗎?
          我覺得與可見性無關(guān),因?yàn)閟ynchronized block已經(jīng)可以保證塊內(nèi)變量的可見性,這里應(yīng)該是變量操作的原子性


          http://en.wikipedia.org/wiki/Double-checked_locking

          posted on 2011-11-21 15:28 tobyxiong 閱讀(232) 評(píng)論(0)  編輯  收藏 所屬分類: java

          <2011年11月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(3)

          隨筆分類(144)

          隨筆檔案(157)

          相冊(cè)

          最新隨筆

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 宁远县| 偏关县| 马龙县| 威远县| 镇康县| 鹤峰县| 河间市| 仁化县| 太保市| 绥滨县| 都江堰市| 娄烦县| 高青县| 红河县| 安西县| 疏附县| 石景山区| 三明市| 德钦县| 黑龙江省| 桃江县| 桦甸市| 宁安市| 铁岭市| 高碑店市| 中阳县| 古浪县| 泽普县| 龙川县| 交口县| 凉山| 大渡口区| 正阳县| 石柱| 德安县| 隆德县| 五原县| 长沙市| 云林县| 浙江省| 镇坪县|