Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

Синглтон на основе DCL

#java #многопоточность


Существует такая реализация синглтона на основе double checked locking (пункт 2):

public class Singleton {
    private static volatile Singleton instance;

    public static Singleton getInstance() {
        Singleton localInstance = instance;
        if (localInstance == null) {
            synchronized (Singleton.class) {
                localInstance = instance;
                if (localInstance == null) {
                    instance = localInstance = new Singleton();
                }
            }
        }
        return localInstance;
    }
}


Вопрос 1: для чего здесь используется localInstance? Почему бы не сделать вот так:

public class Singleton {
    private static volatile Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}


?

У меня есть предположение: чтение volatile-поле обходится несколько дороже, чем чтение
обычного поля, либо локальной переменной, поэтому здесь и используется локальная переменная.
Если я прав и кто-то может расписать этот момент по-подробнее - буду признателен.

Вопрос 2: Почему в данном классе не объявлен приватный конструктор? Ведь в случае
его отсутствия где-то в коде можно явно создать экземпляр данного класса.
    


Ответы

Ответ 1



Это сделано, отчасти из за производительности, отчасти из за того, что если не использовать дополнительной локальной переменной, то код может работать не корректно. А именно, если мы напишем в synchronized : instance = new Singleton(); А Singleton будет иметь, например, такую структуру: class Singleton { private Object obj; Singleton(){ obj = new Object(); } } То, компилятор может заинлайнить конструктор, при этом не сохранив порядок операций. Т.е. может получиться следующее: Создается объект Singleton Присваивается значению instance Инициализируются поля у созданного объекта Такая ситуация называется небезопасной публикацией. Чтобы ее исправить достаточно, определить поля либо final, либо volatile (есть еще варианты). Хорошая статья с примерами на данную тему PS. кому интересно, можете запустить у себя jsctress тест и поиграться с различными вариациями.

Ответ 2



localInstance нужен для повышения производительности этого кода. В случаях, когда instance уже инициализирован(т.е. в большинстве случаев) это позволяет не обращаться к volatile полю второй раз, при return instance вместо return localInstance Источник: Joshua Bloch "Effective Java, Second Edition", p. 283-284 Там он утверждает, что это позволяет добиться прироста производительности в 25% По поводу второго вопроса - полагаю, что приватный конструктор в синглтоне - нечто само собой разумеющееся. Поэтому, при обсуждении более глубоких деталей реализации этот момент допустимо опустить.

Комментариев нет:

Отправить комментарий