В последнее время я смотрю на множество сторонних библиотечных кодов и вижу этот код, который меня смущает

Итак, вот фрагмент кода из статического метода getDefault() EventBus, который возвращает статический экземпляр класса 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 ответ

Решение

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

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

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

Источник

Другие вопросы по тегам