надлежащее использование синхронизируемого одиночного элемента?

Отвечая на мой собственный вопрос, чтобы в будущем кто-то смог сэкономить время. aks-engine имеет эту ошибку, которая хорошо известна. Для решения проблемы воспользуйтесь службой aks из Azure cli или порталом управления, который в настоящее время поддерживает развертывание кластера в существующей VNET.

10
задан Taryn 27 March 2014 в 15:58
поделиться

10 ответов

Двойная проверка блокировки оказалась неправильной и ошибочной (как минимум в Java). Сделайте поиск или посмотрите на статью Википедии для точной причины.

Прежде всего, это правильность программы. Если ваш код не является поточно-ориентированным (в многопоточной среде), то он сломан. Корректность важнее, чем оптимизация производительности.

Чтобы быть точным, вам нужно синхронизировать весь метод getInstance

public static synchronized Singleton getInstance() {
   if (instance==null) ...
}

или статически инициализировать его

private static final Singleton INSTANCE = new Singleton();
30
ответ дан 3 December 2019 в 13:28
поделиться

Использование отложенной инициализации для базы данных в веб-сканере, вероятно, не стоит. Ленивая инициализация добавляет сложность и постоянный удар по скорости. Один случай, когда это оправдано, - когда есть большая вероятность, что данные никогда не понадобятся. Кроме того, в интерактивном приложении его можно использовать для сокращения времени запуска и создания иллюзии скорости.

Для неинтерактивного приложения, такого как веб-сканер, которому, безусловно, потребуется его база данных для Существуют сразу, ленивая инициализация плохо подходит.

С другой стороны, веб-сканер легко распараллеливается и значительно выиграет от многопоточности. Использовать его как упражнение для освоения библиотеки java.util.concurrent было бы крайне полезно. В частности, посмотрите на ConcurrentHashMap и ConcurrentSkipListMap , , которые позволят нескольким потокам читать и обновлять общую карту.

Когда вы избавляетесь от ленивой инициализации, самый простой шаблон Singleton это что-то вроде этого:

class Singleton {

  static final Singleton INSTANCE = new Singleton();

  private Singleton() { }

  ...

}

Ключевое слово final является ключевым здесь. Даже если вы предоставляете статический «геттер» для синглтона, а не прямой доступ к полю, создание синглтона финального помогает обеспечить корректность и позволяет более агрессивную оптимизацию компилятором JIT.

10
ответ дан 3 December 2019 в 13:28
поделиться

Если бы ваша жизнь зависела от нескольких микросекунд, то я бы посоветовал вам оптимизировать блокировку ресурсов так, чтобы это имело значение.

Но в данном случае ключевое слово здесь - hobby project. !

Это означает, что если вы синхронизировали весь метод getInstance () , с вами все будет в порядке в 99,9% всех случаев. Я НЕ рекомендовал бы делать это каким-либо другим способом.

Позже, если вы докажете посредством профилирования, что синхронизация getInstance () является узким местом вашего проекта, тогда вы можете двигаться дальше и оптимизировать параллелизм , Но я действительно сомневаюсь, что это доставит вам неприятности.

Джич!

2
ответ дан 3 December 2019 в 13:28
поделиться

Попробуйте Билл Пью решение инициализации по требованию держателя. Решение является наиболее переносимым среди различных компиляторов Java и виртуальных машин. Решение является поточно-ориентированным и не требует специальных языковых конструкций (т. Е. Энергозависимых и / или синхронизированных).

http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh

2
ответ дан 3 December 2019 в 13:28
поделиться

Если вы посмотрите в самый конец этой статьи, вы увидите предложение просто использовать статическое поле. Это было бы моим уклоном: вам не нужно ленивое создание экземпляров (поэтому вам не нужно, чтобы getInstance () был и средством доступа, и фабричным методом). Вы просто хотите убедиться, что у вас есть одна и только одна из этих вещей. Если вам действительно нужен глобальный доступ к одной такой вещи, я бы использовал этот пример кода в самом низу :

class Singleton
{
  private Vector v;
  private boolean inUse;
  private static Singleton instance = new Singleton();

  private Singleton()
  {
    v = new Vector();
    inUse = true;
    //...
  }

  public static Singleton getInstance()
  {
    return instance;
  }
}

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

Все, что сказано, возможно, что вам действительно нужно, это одна из потоковых структур данных, доступных в современных JDK. Например, я

1
ответ дан 3 December 2019 в 13:28
поделиться

Check out this article Implementing the Singleton Pattern in C#

public sealed class Singleton
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}
0
ответ дан 3 December 2019 в 13:28
поделиться

Почему бы вам не создать структуру данных, которую вы передаете каждому из потоков как внедрение зависимостей. Таким образом, вам не нужен синглтон. Вам все еще нужно сделать поток безопасным.

1
ответ дан 3 December 2019 в 13:28
поделиться

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

0
ответ дан 3 December 2019 в 13:28
поделиться

Как насчет:

public static Singleton getInstance() {
  if (instance == null) {
    synchronize(Singleton.class) {
      if (instance == null) {
         instance = new Singleton();
      }
    }
  }

  return instance;
}
0
ответ дан 3 December 2019 в 13:28
поделиться

как утверждает Джошуа Блох в своей книге "Эффективная java 2-е издание", я также согласен, что одноэлементный тип enum - лучший способ реализовать singleton.

public enum Singleton {
  INSTANCE;

  public void doSomething() { ... }
}
2
ответ дан 3 December 2019 в 13:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: