"Двойная проверка блокировки повреждена" только для Java?

страница http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html говорит, что блокировка с двойным проверкой ошибочна в java. Мне просто интересно, относится ли это также к другим языкам (С#, Vb, С++ и т.д.).

Я читал Двойной проверенный шаблон блокировки: Разбито или нет?, Является ли это ломаной двойной проверенной блокировкой?, Как разрешить "Двойное блокирование блокировки" , Декларация на Java?, чтобы быть правдивой, я не знаю, что такое общий консенсус. некоторые говорят, что его сломанные другие говорят "нет".

В любом случае, мой вопрос в том, относится ли это также к другим языкам (С#, Vb, С++ и т.д.)

Ответы

Ответ 1

Двойная проверенная блокировка в Java безопасна, ПРЕДОСТАВЛЯЕТСЯ, ЧТО:

  • переменная экземпляра объявляется как volatile, AND
  • JVM правильно реализует спецификацию JSR-133; то есть он совместим с Java 5 и более поздними версиями.

Мой источник - это FAQ о JSR-133 (Java Memory Model) - Джереми Мэнсон и Брайан Гетц, февраль 2004 г.. Это подтверждается Goetz в ряде других мест.

Однако, как говорит Гетц, это идиома, время которой прошло. Незаконная синхронизация в Java теперь очень быстрая, поэтому он рекомендует просто объявить метод getInstance() как synchronized, если вам нужно выполнить ленивую инициализацию. (И я полагаю, что это относится и к другим языкам...)

Кроме того, при прочих равных условиях, это плохая идея написать код, который работает на Java 5, но ненадежен в более старых JVM.


Хорошо, а как насчет других языков? Ну, это зависит от того, как реализована идиома, и часто на платформе.

  • С# - согласно fooobar.com/questions/74096/..., зависит от платформы, должна ли переменная экземпляра быть изменчивой. Однако Wikipedia говорит, что если вы используете volatile или явные барьеры памяти, идиома может быть реализована безопасно.

  • VB - согласно Wikipedia идиома может быть реализована безопасно с использованием явных барьеров памяти.

  • С++ - в соответствии с Wikipedia идиома может быть реализована безопасно с помощью volatile в Visual С++ 2005. Но другие источники говорят, что в целом спецификация языка С++ не обеспечивает достаточных гарантий для volatile. Однако блокировка с двойной проверкой может быть реализована в контексте версии языка С++ 2011 - fooobar.com/questions/126649/....

(Примечание: я просто подытоживаю некоторые источники, которые я нашел, которые кажутся мне последними... и звуковыми. Я не эксперт на С++, С# или VB. Пожалуйста, прочитайте связанные страницы и сделайте свои собственные суждения. )

Ответ 3

Это сложный вопрос, в котором есть поле противоправной информации.

Часть проблемы состоит в том, что существует несколько вариантов блокировки с двойной проверкой:

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

И не только это, разные авторы имеют другое определение того, что означает, что шаблон является "правильным".

  • Определение # 1. Широко признанная спецификация языка программирования (например, ECMA для С#) гарантирует правильность шаблона.
  • Определение # 2: шаблон работает на практике в конкретной архитектуре (обычно x86).

Как ни неприятно, как может показаться, много кода там зависит от определения № 2.

В качестве примера возьмем С#. В С# шаблон с двойной проверкой (как обычно реализуется) является правильным в соответствии с определением № 1 тогда и только тогда, когда поле является изменчивым. Но если мы рассмотрим определение № 2, почти все варианты верны для X86 (т.е. Работают), даже если поле является энергонезависимым. В Itanium вариант с одним полем работает, если поле является энергонезависимым, но не двухполюсным вариантом.

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

Ответ 4

Как говорили другие, эта идиома имела свое время. FWIW, для ленивой инициализации .Net теперь предоставляет встроенный класс: System.Lazy<T> (msdn). Не знаю, доступно ли что-то подобное в java.

Ответ 5

Он был ошибочным в Java, он был исправлен на Java 5. Тот факт, что был сломан, был скорее проблемой реализации в сочетании с недоразумением, чем технически "плохая идея".