В последнее время я смотрю на множество сторонних библиотечных кодов и вижу этот код, который меня смущает - PullRequest
0 голосов
/ 25 декабря 2018

Итак, вот фрагмент кода из статического метода EventBus getDefault (), который возвращает статический экземпляр класса EventBus.

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
    EventBus instance = defaultInstance;
    if (instance == null) {
        synchronized (EventBus.class) {
            instance = EventBus.defaultInstance;
            if (instance == null) {
                instance = EventBus.defaultInstance = new EventBus();
            }
        }
    }
    return instance;
}

Я вижу, что код сначала проверяет, является ли экземпляр нулевым, а затем снова в синхронизированном блокеделает ту же проверку еще раз.Почему это так.

Что если я напишу это так.

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
    EventBus instance = defaultInstance;
    if (instance == null) {
        synchronized (EventBus.class) {
            instance = EventBus.defaultInstance = new EventBus();
        }
    }
    return instance;
}

Что-то не так с моей версией?Что мне здесь не хватает?

1 Ответ

0 голосов
/ 25 декабря 2018

В вашем коде два потока могут попасть внутрь оператора if одновременно, когда экземпляр равен нулю.Затем один поток входит в синхронизированный блок для инициализации экземпляра, а другой блокируется.Когда первый поток выходит из синхронизированного блока, ожидающий поток входит и создает еще один объект Singleton.Обратите внимание, что когда второй поток входит в синхронизированный блок, он не проверяет, является ли экземпляр ненулевым.

Итак, мы следуем двойной проверке инициализации, она включает в себя:

  1. Проверьте, что переменная инициализирована (без получения блокировки).Если он инициализирован, немедленно верните его.
  2. Получите блокировку.
  3. Дважды проверьте, была ли переменная уже инициализирована: если другой поток сначала получил блокировку, он, возможно, уже сделалинициализация.Если это так, верните инициализированную переменную.
  4. В противном случае инициализируйте и верните переменную.

Источник

...