2012-12-20 51 views
1

在'Effective Java,Second Edition'中的第71項中,引入了雙重檢查慣用語和單檢查慣用法,用於懶惰地實例化實例字段。使用單一檢查慣用法的懶惰初始化

仔細檢查成語

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { 
    synchronized(this) { 
     result == field; 
     if (result == null) 
     field = result = computeFieldValue(); 
    } 
    } 
    return result; 
} 

單檢成語

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { 
    field = result = computeFieldValue(); 
    } 
    return result; 
} 

在仔細檢查成語約書亞指出,該結果變量用於確保易失性字段僅被讀取一次,這提高了性能。這個我明白了,但是我不明白爲什麼我們需要它在單查成語中,因爲我們一次只讀字段

+0

仔細檢查是過時的,因爲存在多處理器環境: http://www.ibm.com/developerworks/java/library/j -dcl/index.html – alfasin

+4

@alfasin:這篇IBM文章已過時。使用Java 5內存模型並保證使用易變的字段,上面的雙重檢查習慣用法是可以的。 –

+0

內存模型不是這裏唯一的問題,請閱讀「JIT編譯器會在這裏看到一個優化機會......」 – alfasin

回答

5

在單檢查方式中,沒有結果變量,你仍然會讀兩遍;一次用於空值檢查,一次用於返回值。

1

我更喜歡下面的實現懶惰的評價:

@ThreadSafe 
class MyClass { 
    private static class MyClassHelper { 
     public static final MyClass helper = new MyClass(); 
    } 

    public static MyClass getInstance() { 
     return MyClassHelper.helper; 
    } 
} 
+0

不編譯。 –

+1

這是懶惰初始化空間的正確方法。雖然其他方法可以達到相同的效果,但在這裏您可以依賴Classloader來獲得優雅的解決方案。雖然我會讓助手場地最後。 –

+0

它不會編譯,因爲他使用「HelperHolder.helper」而不是「MyClassHelper.holder」,只是一個小小的更改/拼寫錯誤。 –

相關問題