Синглтон в многопоточном - разные сценарии - PullRequest
2 голосов
/ 07 июля 2011

Чем ниже 2 кода отличаются с точки зрения многопоточной среды?

Код 1:

public class Singleton {
private Singleton() {}

private static class SingletonHolder { 
    private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
    return SingletonHolder.INSTANCE;
}
}

Код 2:

class Singleton {
private static Singleton uniqueInstance;

private Singleton() { ... }

public static Singleton getInstance() {
    if (uniqueInstance == null) {
        uniqueInstance = new Singleton();
    }

    return uniqueInstance;
}
}

Почему Код 2 не будетработать в многопоточной среде, когда объявлена ​​статическая переменная, которая будет загружена после загрузки класса и, следовательно, будет иметь только один экземпляр?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 07 июля 2011

Помните, что более чем один поток может вызывать getInstance в данный момент времени.

В примере 1 гарантируется, что инициализатор для члена uniqueInstance будет выполняться только один раз - во время загрузки класса.

В Примере 2, поскольку инициализация происходит встроенным в getInstance, более чем один поток может независимо и одновременно найти переменную-член uniqueInstance равной null.Затем каждый поток будет вызывать new Singleton() с неопределенными результатами, которые зависят от синхронизации двух (или более) потоков.

Для работы примера 2 можно (например) добавить synchronized наgetInstance method.

Ваш комментарий о том, что переменная полностью инициализирована во время загрузки класса, верен для примера 1, но не для 2 - в примере 2 переменная-член установлена ​​на null во время загрузки класса, но заполняется экземпляром объекта позже, во время первого вызова (вызовов) до getInstance.

1 голос
/ 07 июля 2011

Несколько нитей могут быть внутри:

if (uniqueInstance == null) {
...
}

состояние одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...