В этом примере, я полагаю, вы захотите синхронизировать свой метод getInstance (), чтобы два потока не одновременно вводили его. В противном случае два потока могут оказаться внутри блока, где создается экземпляр singleton, что очень проблематично. Единственная проблема с этим решением - вы платите премию за синхронизацию метода каждый раз, когда вызывается getInstance ().
Пример:
public static synchronized Singleton getInstance()
{
// since whole method is synchronized only 1 thread can
// enter the following block ensuring only one instance
// is ever created. however we pay a synchronization
// penalty every time this method is called.
if(mInstance==null) {
mInstance=new Singleton();
}
return mInstance;
}
В качестве альтернативы вы также можете переключиться на использование быстрой инициализации экземпляра синглтона, а не на отложенную инициализацию, если инициализация дешевая, что гарантирует параллелизм, а также не платит синхронизированный штраф за вызов метода getInstance ().
Пример:
// no synchronization penalty, but penalty for eager init
private static Singleton mInstance = new Singleton();
public static Singleton getInstance()
{
return mInstance;
}
Наиболее оптимизированный подход заключается в использовании двойной проверки блокировки, что необходимо для надежной работы с Java 1.5 или новее из-за различных реализаций ключевого слова volatile в 1.4 или более ранних версиях JVM (см. Главу 5 «Сначала шаблоны проектирования»). стр.182, опубликованная O'Reilly Media, Inc. - именно здесь я впервые прочитал об этом.)
Пример:
private volatile static Singleton mInstance;
private Singleton(){}
public static Singleton getInstance()
{
if(mInstance==null) {
synchronized (Singleton.class) {
// only pay synchronization penalty once
if(mInstance==null){
mInstance=new Singleton();
}
}
}
return mInstance;
}