簡體   English   中英

Gregory Kick了解dagger2 ScopedProvider中的惰性初始化單例

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM