Есть ли у Java фиаско инициализации статического порядка? - PullRequest
10 голосов
/ 07 июля 2011

Недавний вопрос здесь содержал следующий код (ну, похожий на этот) для реализации синглтона без синхронизации.

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 есть эта проблема? Я знаю, что порядок в пределах полностью указан, но гарантирует ли это какой-либо последовательный порядок между классами (например, с помощью загрузчика классов)?

Во-вторых, если порядок является непротиворечивым, то почему бы ленивый вариант строительства был бы выгоден?

Ответы [ 11 ]

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

Вы инициализируете с нетерпением, потому что вам не нужно писать синхронизированный блок или метод.Это в основном потому, что синхронизация обычно считается дорогой

...