[英]Understanding lazy initialization singleton in dagger2 ScopedProvider by Gregory Kick
我正在閱讀Dagger2的源代碼,並且在ScopedProvider
有一個靜態字段UNINITIALIZED
,它指示instance
字段尚未初始化。 我已經閱讀並理解了double-check-lazy-initialization習慣用法,但是為什么有必要定義UNINITIALIZED
字段而不是僅使用null
呢? 與JVM有關嗎?
/**
* A {@link Provider} implementation that memoizes the result of a {@link Factory} instance.
*
* @author Gregory Kick
* @since 2.0
*/
public final class ScopedProvider<T> implements Provider<T> {
private static final Object UNINITIALIZED = new Object();
private final Factory<T> factory;
private volatile Object instance = UNINITIALIZED;
private ScopedProvider(Factory<T> factory) {
assert factory != null;
this.factory = factory;
}
@SuppressWarnings("unchecked") // cast only happens when result comes from the factory
@Override
public T get() {
// double-check idiom from EJ2: Item 71
Object result = instance;
if (result == UNINITIALIZED) {
synchronized (this) {
result = instance;
if (result == UNINITIALIZED) {
instance = result = factory.get();
}
}
}
return (T) result;
}
/** Returns a new scoped provider for the given factory. */
public static <T> Provider<T> create(Factory<T> factory) {
if (factory == null) {
throw new NullPointerException();
}
return new ScopedProvider<T>(factory);
}
}
看起來這是一個懶惰的null安全初始化。 想象一下,如果工廠返回的是null,而該代碼而不是UNINITIALIZED,則使用null作為前哨值。 每次調用get()都會進入同步塊,因為它不知道null是否實際上是出廠結果,而不僅僅是未初始化的狀態。
此代碼允許工廠返回null並將結果正確存儲在volatile字段中,以便后續讀取不會產生完全同步的開銷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.