<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我的java天地

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

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

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

    很可惜,這樣的寫法在很多平臺和優化編譯器上是錯誤的。

    原因在于:helper = new Helper()這行代碼在不同編譯器上的行為是無法預知的。一個優化編譯器可以合法地如下實現helper = new Helper():

    1. helper = 給新的實體分配內存

    2. 調用helper的構造函數來初始化helper的成員變量

    現在想象一下有線程A和B在調用getHelper,線程A先進入,在執行到步驟1的時候被踢出了cpu。然后線程B進入,B看到的是 helper已經不是null了(內存已經分配),于是它開始放心地使用helper,但這個是錯誤的,因為在這一時刻,helper的成員變量還都是缺 省值,A還沒有來得及執行步驟2來完成helper的初始化。

    當然編譯器也可以這樣實現:

    1. temp = 分配內存

    2. 調用temp的構造函數

    3. helper = temp

    如果編譯器的行為是這樣的話我們似乎就沒有問題了,但事實卻不是那么簡單,因為我們無法知道某個編譯器具體是怎么做的,因為在Java的 memory model里對這個問題沒有定義(C++也一樣),而事實上有很多編譯器都是用第一種方法(比如symantec的just-in-time compiler),因為第一種方法看起來更自然。

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

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


    版本四:目前知道最后版。實際應用時需驗證一下
    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;  
    }  

    因為存在Out-of-order writes現象,所以這里volatile關鍵字是在當instance被初始化給Singleton實例時保證多線程正確地處理instance變量,那這里與線程間的可見性有關嗎?
    我覺得與可見性無關,因為synchronized block已經可以保證塊內變量的可見性,這里應該是變量操作的原子性


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

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

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

    導航

    統計

    常用鏈接

    留言簿(3)

    隨筆分類(144)

    隨筆檔案(157)

    相冊

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 免费永久看黄在线观看app| 亚洲视频在线免费播放| 免费观看日本污污ww网站一区| 亚洲av永久无码嘿嘿嘿| 小草在线看片免费人成视久网| 在线日韩日本国产亚洲| sihu国产精品永久免费| 久久精品国产精品亚洲人人 | 亚洲视频一区在线观看| 无码av免费一区二区三区| 亚洲va在线va天堂va四虎| 热re99久久6国产精品免费| 久久亚洲AV成人无码电影| 免费观看美女用震蛋喷水的视频 | 亚洲视频一区在线| 色se01短视频永久免费| 国产亚洲中文日本不卡二区| 好吊妞788免费视频播放| 春暖花开亚洲性无区一区二区| 免费日本黄色网址| yellow免费网站| 亚洲A∨无码一区二区三区| h视频在线观看免费完整版| 亚洲日韩中文字幕一区| 啊灬啊灬别停啊灬用力啊免费看| ssswww日本免费网站片| 亚洲综合精品香蕉久久网97| 免费无码A片一区二三区| 黄页网站在线免费观看| 亚洲av最新在线网址| 精品久久久久成人码免费动漫 | 99久久免费国产精精品| 自怕偷自怕亚洲精品| 热久久精品免费视频| 午夜成人无码福利免费视频| 亚洲一区二区三区偷拍女厕 | 久久免费国产视频| 亚洲三级在线免费观看| 亚洲精品国产自在久久| 美女内射毛片在线看免费人动物| 亚洲欧美在线x视频|