изменчивый с семантикой выпуска / получения

Начиная с Java 5, ключевое слово volatile имеет семантику выпуска / получения, чтобы сделать побочные эффекты видимыми для других потоков (включая присвоение энергонезависимым переменным!). Возьмем, к примеру, эти две переменные:

int i;
volatile int v;

Обратите внимание, что i - это обычная энергонезависимая переменная. Представьте себе поток 1, выполняющий следующие операторы:

i = 42;
v = 0;

Позже поток 2 выполняет следующие инструкции:

int some_local_variable = v;
print(i);

Согласно модели памяти Java, запись v в потоке 1 с последующим чтением v в потоке 2 гарантирует, что поток 2 видит запись в i, выполняемую в потоке 1, поэтому печатается значение 42.

Мой вопрос: есть ли у volatile такая же семантика выпуска / получения в C #?


person fredoverflow    schedule 29.06.2011    source источник
comment
Не совсем; см. blogs.msdn.com/b/ericlippert/archive/2011/06/16/   -  person Robert Harvey    schedule 29.06.2011


Ответы (2)


Семантика «volatile» в C # определена в разделах 3.10 и 10.4.3 спецификации. Вместо того, чтобы воспроизводить их здесь, я рекомендую вам поискать это в спецификации, а затем решить, что использование «volatile» слишком сложно и опасно, и вернуться к использованию блокировок. Я всегда так делаю.

См. 3.10 Порядок выполнения и 10.4.3 Volatile Fields.

person Eric Lippert    schedule 29.06.2011
comment
Попытка отвлечь программистов на C ++ от сложных и опасных деталей, вероятно, приведет к обратному эффекту;) - person fredoverflow; 30.06.2011
comment
@Fred Так вас интересует volatile, потому что это сложно и опасно? - person David Heffernan; 30.06.2011
comment
@David: Мне просто не нравятся неточные знания, и у меня сложилось впечатление, что volatile - одно из самых неправильно понимаемых ключевых слов. Я хочу знать, как все работает, вот и все :) - person fredoverflow; 30.06.2011
comment
@Fred Мне нравится знать, как все работает, но я не чувствую необходимости изучать что-то ради этого. Возможно, я слишком стар для этого! - person David Heffernan; 30.06.2011

Что ж, я считаю, что это гарантирует, что если some_local_variable читается как 0 (из-за записи в v), i будет прочитан как 42.

Сложная часть - «когда-нибудь позже». Хотя обычно о волатильности говорят в терминах «промывки» записи, это не то, как это на самом деле определяется в спецификации (Java или C #).

Из спецификации языка C # 4, раздел 10.5.3:

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

  • Чтение изменчивого поля называется изменчивым чтением. Неустойчивое чтение имеет «семантику приобретения»; то есть гарантируется, что это произойдет до любых обращений к памяти, которые происходят после него в последовательности команд.
  • Запись изменчивого поля называется изменчивой записью. У изменчивой записи есть «семантика выпуска»; то есть это гарантированно произойдет после любых обращений к памяти до инструкции записи в последовательности инструкций.

Затем есть пример, который вполне похож на ваш, но зависит от значения, считанного из изменчивой переменной.

И, как и Эрик, я бы категорически не полагался на volatile. Об этом трудно рассуждать, и лучше оставить это Джо Даффи / Стивен Тубс мира.

person Jon Skeet    schedule 29.06.2011
comment
Не могли бы вы уточнить, что вы имеете в виду в отношении сброса записи в Java? Вы имеете в виду, что мой код даже не работает на Java? - person fredoverflow; 30.06.2011
comment
@Fred Хорошо, если мы поверим небольшой цитате Джона, похоже, что C # действительно гарантирует семантику выпуска для записи и приобретает семантику для чтения, что означает, что да, пример будет нормально работать как на java, так и на C # ... и теперь вам все еще нужно прочтите важные разделы, чтобы не пропустить какой-нибудь угловой случай. И хотя я могу полностью понять, почему отказ от volatile (а также семафоров и всего прочего низкоуровневого многопоточности) в целом неплохая идея, я также ненавижу пробелы в своих знаниях - и только потому, что вы знаете, как использовать volatile, не это не значит, что вы должны! - person Voo; 30.06.2011
comment
@Fred: Проблема в том, что через некоторое время вы не определили, что имеете в виду. Вы можете гарантировать, что если поток 2 увидит запись в изменчивую переменную, то он также увидит запись в энергонезависимую переменную. - person Jon Skeet; 30.06.2011