Java double check lock singleton должен использовать ключевое слово volatile? [Дубликат]

int first_value = Integer.parseInt(cards[index]); 

при написании вышеуказанного утверждения вы пытаетесь разобрать «Туз клубов» как число.

вы можете использовать следующий метод, чтобы проверить, может ли какая-либо строка быть проанализирована как Integer:

boolean tryParseInt(String value) {  
     try {  
         Integer.parseInt(value);  
         return true;  
      } catch (NumberFormatException e) {  
         return false;  
      }  
}

Что касается вашего вопроса, то что такое NumberFormatException: указывается, что приложение попытался преобразовать строку в один из числовых типов, но строка не имеет соответствующего формата. (ref - http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html )

55
задан Ravindra babu 17 October 2016 в 18:17
поделиться

7 ответов

Ну, нет никакой двойной проверки блокировки для производительности. Это паттерна .

Оставляя эмоции в стороне, volatile здесь, потому что без него к тому времени, когда второй поток проходит instance == null, первая нить не может построить new Singleton() все же: никто не обещает, что создание объекта происходит до присваивания instance для любого потока, кроме фактически создающего объект.

volatile в свою очередь устанавливает происходит до отношения между чтением и записью и исправляет разбитый шаблон.

Если вы ищете производительность, используйте вместо этого внутренний статический класс.

52
ответ дан alf 17 August 2018 в 23:59
поделиться
  • 1
    Хорошо, похоже, что новая реализация волатильности устраняет проблемы с памятью с помощью DCL. То, что я до сих пор не получаю, - это влияние производительности использования volatile здесь. Из того, что я прочитал, изменчивость в значительной степени медленна, чем синхронизация, поэтому почему бы просто не синхронизировать весь метод getInstance ()? – toc777 21 October 2011 в 23:39
  • 2
    @ toc777 volatile медленнее обычного. Если вы ищете производительность, пойдите для шаблона класса владельца. volatile здесь просто для того, чтобы показать, что существует способ , чтобы заставить сломанный шаблон работать. Это скорее проблема кодирования, чем настоящая проблема. – alf 21 October 2011 в 23:43
  • 3
    @alf объясняет многое, спасибо. В этой книге они совершенно не понимали. – toc777 21 October 2011 в 23:51
  • 4
    @ Тит хорошо, синглтон в XML по-прежнему остается одиночным; понимание состояния времени выполнения приложения не облегчается с помощью DI. меньшие единицы кода могут казаться более простыми, за счет сильной структуризации всех единиц, чтобы соответствовать DI-идиоме (хорошая вещь, о которой можно было бы сказать). Обвинение против синглтона несправедливо, оно сбивает API с impl - Foo.getInstance() - просто выражение, чтобы каким-то образом получить Foo, оно ничем не отличается от @Inject Foo foo; в любом случае сайт, который запрашивает Foo, является агностиком, из которого возвращается Foo, и каким образом статические и временные зависимости одинаковы. – irreputable 22 October 2011 в 04:18
  • 5
    @irreputable. Вы знаете, что смешно в том, что в то время, когда у нас был этот обмен, я никогда не использовал Spring и не имел в виду весенний DI. Настоящая опасность с Синглтоном как static factory - это соблазн называть его глубоко внутри кода, который не должен знать о методе getInstance() и вместо этого требовать предоставления экземпляра. – Tim Bender 8 June 2013 в 03:05
  • 6
    Исправлено, спасибо @ Kapol! – alf 10 August 2017 в 13:11
  • 7
    hi @ alf. Согласно случаям - до определения, после того, как один поток освобождает блокировку, другой поток получает блокировку, а затем последний может видеть предыдущее изменение. Если это так, я не думаю, что ключевое слово volatile необходимо. Можете ли вы объяснить это более подробно – Qin Dong Liang 5 July 2018 в 02:21
  • 8
    Но нет блокировки в случае, если второй поток попадает только наружу, если нет, поэтому никакого упорядочения. – alf 5 July 2018 в 08:47
53
ответ дан alf 6 September 2018 в 15:49
поделиться
53
ответ дан alf 29 October 2018 в 22:07
поделиться

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

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

1
ответ дан corsiKa 17 August 2018 в 23:59
поделиться
  • 1
    Согласно случаям - до определения, после того, как один поток освобождает блокировку, другой поток получает блокировку, а затем последний может видеть предыдущее изменение. Если это так, я не думаю, что ключевое слово volatile необходимо. Можете ли вы объяснить это более подробно – Qin Dong Liang 5 July 2018 в 02:32
  • 2
    @QinDongLiang Если переменная не является изменчивой, второй поток может использовать кешированное значение в своем стеке. Будучи изменчивым, он возвращается к источнику, чтобы получить правильное значение. Конечно, он должен делать это при каждом доступе и, следовательно, может иметь удар производительности (но будем честными, если только он не находится в суперкритической петле, это, вероятно, не самое худшее в вашей системе ...) – corsiKa 5 July 2018 в 03:43

Объявление переменной как volatile гарантирует, что все обращения к ней фактически считывают текущее значение из памяти.

Без volatile компилятор может оптимизировать доступ к памяти и сохранить ее значение в регистр, поэтому только первое использование переменной считывает фактическую ячейку памяти, содержащую переменную. Это проблема, если переменная изменена другим потоком между первым и вторым доступом; первый поток имеет только копию первого (предварительно измененного) значения, поэтому второй оператор if проверяет устаревшую копию значения переменной.

0
ответ дан David R Tribble 17 August 2018 в 23:59
поделиться
  • 1
    -1 Сегодня я теряю свои очки репутации :) Причина real заключается в том, что есть кеш памяти, смоделированный как локальная память потока. Порядок, в котором локальная память сбрасывается на главный, не определена, т. Е. Если у вас есть отношения происходит до , например, с помощью volatile. Регистры не имеют ничего общего с неполными объектами и проблемой DCL. – alf 21 October 2011 в 23:14
  • 2
    Ваше определение volatile слишком узкое - если все это было волатильно, двойная проверенная блокировка отлично работала бы в & lt; Java5. volatile вводит барьер памяти, делающий определенное переупорядочение незаконным - без этого, даже если мы никогда не будем читать устаревшие значения из памяти, он все равно будет небезопасным. Редактировать: alf избил меня до этого, не должен был получить хороший чай;) – Voo 21 October 2011 в 23:18
  • 3
    @TimBender, если singleton содержит изменяемое состояние, его очистка не имеет никакого отношения к ссылке на сам синглтон (ну, есть косвенная ссылка, поскольку доступ к ссылке volatlie к singleton делает ваш поток повторно -read main memory - но это вторичный эффект, а не причина проблемы :)) – alf 21 October 2011 в 23:18
  • 4
    @alf, ты прав. И фактически создание volatile vol не помогает, если внутреннее состояние изменено, поскольку флеш происходит только в том случае, если сама ссылка изменена (например, при создании массивов / списков volatile ничего не делает для содержимого). Мел это до мозгового пердуна. – Tim Bender 21 October 2011 в 23:22
  • 5
    Согласно случаям - до определения, после того, как один поток освобождает блокировку, другой поток получает блокировку, а затем последний может видеть предыдущее изменение. Если это так, я не думаю, что ключевое слово volatile необходимо. Не могли бы вы объяснить это подробнее @Tim Bender – Qin Dong Liang 5 July 2018 в 02:35

Неустойчивое чтение не очень дорого само по себе.

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

Другой impl с помощью поля final (см. wikipedia). Для этого требуется дополнительное чтение, которое может стать дороже, чем версия volatile. Версия final может быть быстрее в узком цикле, однако этот тест является спорным, как ранее утверждалось.

1
ответ дан irreputable 17 August 2018 в 23:59
поделиться

Как цитируется @irreputable, volatile не дорогая. Даже если это дорого, согласованность должна быть отдана приоритету над производительностью.

Есть еще один чистый элегантный способ для Lazy Singletons.

public final class Singleton {
    private Singleton() {}
    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
    private static class LazyHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
}

Исходная статья: Инициализация-по-запросу_holder_idiom из википедии

< blockquote>

В программной инженерии идиома Инициализация по требованию (шаблон дизайна) - это ленивый загруженный синглтон. Во всех версиях Java идиома обеспечивает безопасную, очень параллельную ленивую инициализацию с хорошей производительностью

. Поскольку у класса нет инициализируемых переменных static, инициализация завершается тривиально.

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

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

Это решение является потокобезопасным, не требуя специальных языковых конструкций (т.е. volatile или synchronized).

10
ответ дан Ravindra babu 17 August 2018 в 23:59
поделиться
Другие вопросы по тегам:

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