"Двойная проверка блокировки заблокирована" только для Java? - PullRequest
15 голосов
/ 11 мая 2011

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

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

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

Ответы [ 5 ]

9 голосов
/ 11 мая 2011

Блокировка с двойной проверкой безопасна на Java, при условии, что:

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

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

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

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


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

  • C # - в соответствии с https://stackoverflow.com/a/1964832/139985, это зависит от платформы, требуется ли переменной экземпляра для волатильности. Однако Википедия говорит, что если вы используете volatile или явные барьеры памяти, идиома может быть реализована безопасно.

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

  • C ++ - согласно Wikipedia идиома может быть безопасно реализована с использованием volatile в Visual C ++ 2005. Но другие источники говорят, что в общем спецификация языка C ++ не не предоставить достаточных гарантий для volatile, чтобы быть уверенным. Однако двойная проверка блокировки может быть реализована в контексте языковой ревизии C ++ 2011 - https://stackoverflow.com/a/6099828/139985.

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

3 голосов
/ 11 мая 2011

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

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

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

И не только это, разные авторы по-разному определяют, что означает «правильный» шаблон.

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

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

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

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

3 голосов
/ 11 мая 2011

Эта статья в Википедии посвящена java, c ++ и .net (c # / vb) http://en.wikipedia.org/wiki/Double-checked_locking

2 голосов
/ 11 мая 2011

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

1 голос
/ 11 мая 2011

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

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