Есть ли проблемы в многопоточной среде с шаблоном Singleton? - PullRequest
1 голос
/ 30 ноября 2011

Я реализовал класс Singleton, как показано ниже:

public class Singleton {

    private static  Singleton instance = null;


    private Singleton() { 
    }

private synchronized static void createInstance() {
    instance = new Singletone();
}


    public static Singleton getInstance() {
        if(instance == null){
            createInstance();
        }
        return instance;
    }

}

Но я хочу знать, является ли это правильной реализацией синглтона.Есть ли проблемы в многопоточной среде.

Ответы [ 7 ]

7 голосов
/ 30 ноября 2011
public enum Singleton {
    INSTANCE;
    private int val;

    public int getVal() {
        return val;
    }
}

Использование:

Singleton.INSTANCE.getVal();

Это идеальный синглтон для версий Java> 5.0, где у вас есть поддержка enum.

Также упоминается в «Эффективной Java» Джошуа Блоха. Сообщение в блоге об этом здесь: Enum Singleton

Обновление:
Также, пожалуйста, используйте синглтоны только тогда, когда вы уверены на 100%! Это убивает тестируемость кода! Но вы не можете избежать этого в некоторых местах, скажем, на фабрике.
Но, пожалуйста, не злоупотребляйте этим, используйте его там, где он вам действительно нужен. Понять его использование.

5 голосов
/ 30 ноября 2011

Ваша реализация почти правильная.Проблема в том, что он не является поточно-ориентированным.2 отдельных потока могут одновременно вводить getInstance(), проверить, что экземпляр равен нулю, а затем создать 2 экземпляра вашего класса.Вот исправление:

public static synchronized Singletone getInstance() {
    if(instance == null){
        createInstance();
    }
    return instance;
} 

Обратите внимание на слово synchronized.

2 голосов
/ 30 ноября 2011

Лучший механизм, с которым я столкнулся, кроме перечисленного выше, называется статической инициализацией. При этом вы полагаетесь на гарантии модели памяти Java, поэтому она всегда будет работать. Вот фрагмент из ответа на другой вопрос , который демонстрирует это:

class Singleton {
   static class SingletonHolder {
      static final Singleton INSTANCE = new Singleton();
   }
   public static Singleton instance() {
      return SingletonHolder.INSTANCE;
   }
}

Объект класса SingletonHolder с экземпляром Singleton будет создан при первом вызове SingletonHolder.INSTANCE.

Модель памяти Java гарантирует, что статический код (new Singleton()) будет выполняться только одним потоком. Таким образом, нет двойной проверки блокировки (которая не работает) и нет ненужной синхронизации. Все последующие вызовы будут получать этот экземпляр.

0 голосов
/ 30 ноября 2011

Для реализации отложенной инициализации, которая в вашем случае, метод getInstance () должен быть синхронизирован для обеспечения безопасности потока.

public static synchronized Singleton getInstance()

Или вы можете просто инициализировать его во время загрузки класса, которое уже поточно-ориентировано.

private static  Singleton instance = new MySingleton(); 
0 голосов
/ 30 ноября 2011

Singleton не безопасен для потоков.Именно по этой причине была введена Двойная проверка блокировки .

Начиная с Java SE 5 и выше, вы можете volatile свой статический экземпляр.Виртуальная машина Java будет знать, как правильно обрабатывать Singleton при запуске нескольких потоков.

Подробнее о Двойная проверка блокировки .

0 голосов
/ 30 ноября 2011

Ваша реализация выглядит просто отлично. Многопоточность в одной JVM не является проблемой для такого рода одноэлементных проблем, но она вызовет проблемы в кластеризованных (двух или более JVM).

См. http://java.sun.com/developer/technicalArticles/Programming/singletons/ об этих проблемах.

О, и это синглтон, а не синглетон. :)

0 голосов
/ 30 ноября 2011

Это правильная реализация шаблона синглтона, хотя вам не нужен метод createInstance;Вы можете просто вставить это в getInstance.Кроме того, оно написано «Синглтон», без «е» в конце.

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

Хотя это зависит от того, как вы его используете.Если вы используете синглтон перед настройкой потоков, проблем не будет.Если это проблема, вы можете сначала инициализировать синглтон.Вы также можете решить эту проблему, используя ключевое слово synchronized в объявлении метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...