我一直在使用LazyReference
類幾年(當然不定期,但有時它是非常有用的)。這個班級可以看到here。學分由Robbie Vanbrabant(班級作者)和Joshua Bloch着名的「Effective Java 2nd edt」完成。 (原始碼)。LazyReference與雙重檢查鎖定和空處理
該類可正常工作(在Java 5+中),但存在一個小小的潛在問題。如果instanceProvider
返回null
(當然,它不能根據Guice Provider.get()
合同,但是...),然後在每次執行LazyReference.get()
方法時,LOCK將被保留並且instanceProvider.get
將被一次又一次地調用。對於那些違反合同的人來說,這看起來是一種很好的懲罰(但他),但如果真的需要懶惰地初始化一個領域並設置價值的可能性呢?
我修改LazyReference一點點:
public class LazyReference<T> {
private final Object LOCK = new Object();
private volatile T instance;
private volatile boolean isNull;
private final Provider<T> instanceProvider;
private LazyReference(Provider<T> instanceProvider) {
this.instanceProvider = instanceProvider;
}
public T get() {
T result = instance;
if (result == null && !isNull) {
synchronized (LOCK) {
result = instance;
if (result == null && !isNull) {
instance = result = instanceProvider.get();
isNull = (result == null);
}
}
}
return result;
}
}
恕我直言應該只是罰款(如果你有另一種意見,請發表您的意見和批評)。但我想知道如果我從isNull
布爾值中刪除volatile
修飾符會發生什麼?(當然,將它留給instance
)?它會繼續正常工作嗎?
'實例不需要易變 - - 好點!由於'instance'寫在volatile初始化字段之前,所有其他讀取'initialized'的線程都會看到它。 – Idolon