Как пишет @irreputable, volatile не дорогая. Даже если это дорого, согласованность должна быть приоритетной над производительностью.
Есть еще один чистый элегантный способ для Lazy Singletons.
public final class Singleton {
private Singleton() {}
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
}
Источник статьи: Initialization-on-demand_holder_idiom из Википедии
В разработке программного обеспечения идиома Инициализация по требованию (шаблон проектирования) - это загружаемый ленивый синглтон. Во всех версиях Java идиома обеспечивает безопасную высококонкурентную ленивую инициализацию с хорошей производительностью
Поскольку класс не имеет static
переменных для инициализации, инициализация завершается тривиально.
Определение статического класса LazyHolder
внутри него не инициализируется, пока JVM не определит, что LazyHolder должен быть выполнен.
Статический класс LazyHolder
выполняется только тогда, когда статический метод getInstance
вызывается для класса Singleton, и в первый раз, когда это происходит, JVM загрузит и инициализирует класс LazyHolder
.
Это решение является поточно-ориентированным и не требует специальных языковых конструкций (т.е. volatile
или synchronized
).