雙重檢測鎖的缺陷

雙重檢測鎖實(shí)現(xiàn)的單例模式看起來非常完美,實(shí)則會出現(xiàn)同步問題。

public MyObject{
    private static MyObect instance;
    private Date d = new Data();
    public Data getD(){return this.d;}
    public static MyObect getInstance(){
        if(instance == null){
            synchronized(MyObect .class){ // 1
                if(instance == null) // 2
                    instance = new MyObject(); // 3
            }
        }
        return instance;
    }
}

1處會將線程進(jìn)行同步。

2處會再次檢查是否已經(jīng)被其他線程實(shí)例化。

3處會出現(xiàn)JVM內(nèi)存模型允許所謂的無序?qū)懭?/code>,如下

1: mem = allocate();        //Allocate memory for Singleton object.
2: instance = mem;          //Note that instance is now non-null, but
                         //has not been initialized.
3: ctorSingleton(instance); //Invoke constructor for Singleton passing

在2之后 instance 給了一個空白空間 mem,已經(jīng)不為空。
因?yàn)榇藭r線程未離開 synchronized 塊,所有 instance 所有的數(shù)據(jù)都未初始化且未同步。

當(dāng)線程1離開 synchronized 塊,如果由于線程間可見性問題可能導(dǎo)致其他線程 獲取的 instance對象對應(yīng)的 mem空間可能是 線程1未寫回的空白空間,這時訪問 getD()為空
這便是同步缺陷。

也可以使用貪婪方式,直接在類加載時初始化instance。

public MyObject{
    private static MyObect instance = new MyObject();
    private Date d = new Data();
    public Data getD(){return this.d;}
    public static getInstance(){
        return instance;
    }
}

Lazy-init的同步實(shí)現(xiàn)其實(shí)可以讓jvm去實(shí)現(xiàn)。如下

public MyObject{

    private static class InstanceHoder{ //內(nèi)部私有的類。
        static MyObject instance = new MyObject();
    }
    private Date d = new Data();
    public Data getD(){return this.d;}
    public static MyObect getInstance(){
           return InstanceHoder.instance;
    }
}

InstanceHoder內(nèi)部類只有在使用到時候才會加載。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 錯誤的雙重檢查鎖 在Java多線程的程序中,為了降低初始化類和創(chuàng)建對象的開銷,經(jīng)常會使用延遲初始化的方式,延遲初始...
    WeiAzure閱讀 545評論 0 0
  • 雙重鎖的由來 單例模式中,有一個DCL(雙重鎖)的實(shí)現(xiàn)方式。在Java程序中,有時候可能需要推遲一些高開銷的對象初...
    小愚笨閱讀 908評論 0 0
  • 定義:整個系統(tǒng)只允許存在一個實(shí)例首先 我們一般都這樣 但這樣在多線程時會存在問題多個線程同時運(yùn)行到if (inst...
    桑榆非晚95閱讀 985評論 0 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,706評論 18 399
  • 在Java多線程程序中,有時候需要采用延遲初始化來降低初始化類和創(chuàng)建對象的開銷。雙重檢查鎖定是常見的延遲初始化技術(shù)...
    ycyoes閱讀 473評論 0 0

友情鏈接更多精彩內(nèi)容