Недавний вопрос здесь содержал следующий код (ну, похожий на этот) для реализации синглтона без синхронизации.
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
Теперь, я думаю, понимаю, что это делает. Поскольку экземпляр является static final
, он создается задолго до того, как какой-либо поток вызовет getInstance()
, поэтому в действительности нет необходимости в синхронизации.
Синхронизация потребовалась бы только в том случае, если два потока пытались вызвать getInstance()
одновременно (и этот метод создавался при первом вызове, а не во "static final"
времени).
Поэтому мой вопрос в основном так: почему тогда вы бы предпочли ленивую конструкцию синглтона с чем-то вроде:
public class Singleton {
private Singleton() {}
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}
}
Я думал только о том, что при использовании метода static final
может возникнуть проблема секвенирования, как в фиаско статического порядка инициализации C ++.
Прежде всего, в Java есть эта проблема? Я знаю, что порядок в пределах полностью указан, но гарантирует ли это какой-либо последовательный порядок между классами (например, с помощью загрузчика классов)?
Во-вторых, если порядок является непротиворечивым, то почему бы ленивый вариант строительства был бы выгоден?