C # - действительно ли "volatile" действительно необходимо в качестве ключевого слова? - PullRequest
13 голосов
/ 21 августа 2010

Когда я все глубже и глубже читаю значение ключевого слова volatile, я продолжаю говорить себе: «Это путь к реализации , это не должно быть частью языка программирования высокого уровня».
Я имею в виду, тот факт, что процессоры кэшируют данные, должен быть интересен для JIT-компилятора, а не для программиста C #.

Значительной альтернативой может быть атрибут (скажем, VolatileAttribute).

Что вы думаете?

Ответы [ 5 ]

8 голосов
/ 21 августа 2010

Я думаю, что вас отвлекли.Все технические вещи о кешировании и т. Д. Являются частью попытки объяснить это в терминах низкого уровня.Функциональное описание для volatile будет «Я мог бы поделиться».Учитывая, что по умолчанию ничто не может быть разделено между потоками, это не совсем странно.И я думаю, что это достаточно фундаментально, чтобы гарантировать ключевое слово над атрибутом, но я полагаю, что на него в значительной степени повлияли исторические решения (C ++)

Один из способов заменить / оптимизировать его - вызовы VolatileRead () и VolatileWrite ().Но это еще более «реализация».

5 голосов
/ 21 августа 2010

Ну, я, конечно, согласен, довольно ужасно, что такая деталь реализации раскрыта. Однако это та же самая деталь, которая раскрывается ключевым словом lock . Мы все еще очень далеки от того, чтобы этот генератор ошибок был полностью удален из нашего кода.

У ребят из железа много работы. Ключевое слово volatile имеет большое значение для ядер ЦП со слабой моделью памяти. Рынок не был добр к ним, Альфа и Итаниум не преуспели. Не совсем понятно почему, но я подозреваю, что сложность написания однопоточного кода для этих ядер во многом связана с этим. Неправильное восприятие - это настоящий кошмар для отладки. К этим процессорам относится словоблудие в документации библиотеки MSDN для volatile, в противном случае оно совершенно не подходит для ядер x86 / x64 и говорит о том, что ключевое слово делает гораздо больше, чем на самом деле. Volatile просто предотвращает сохранение значений переменных в регистрах ЦП этих ядер.

К сожалению, volatile все еще имеет значение для ядер x86 в очень избранных обстоятельствах. Я еще не нашел никаких доказательств того, что это имеет значение для ядер x64. Насколько я могу судить, и подкрепленная исходным кодом в SSCLI20, инструкция Opcodes.Volatile не предназначена для джиттера x64, не изменяя ни состояние компилятора, ни генерацию машинного кода. Это правильный путь.

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

4 голосов
/ 21 августа 2010

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

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

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

Кроме того, вы, кажется, смущены "подробностями реализации".Термин относится к вещам, которые компилятор делает за вашей спиной.Это не тот случай, здесь. Ваш код изменяет переменную вне поля зрения компилятора.Так как он в вашем коде, он всегда будет верным.Следовательно, язык должен указывать на это.

2 голосов
/ 21 августа 2010

volatile в c # испускает правильные барьеры или заборы, которые будут иметь значение для программиста, выполняющего многопоточную работу.Имейте в виду, что компилятор, среда выполнения и процессор могут в некоторой степени переупорядочивать операции чтения / записи (у каждого свои правила).Хотя CLR 2.0 имеет более сильную модель памяти, чем то, что определяет CLI ECMA, модель памяти CLR все еще не является самой строгой моделью памяти, поэтому вам нужно volatile в C #.

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

2 голосов
/ 21 августа 2010

IIIRC, в C ++ volatile была в основном связана с вводом-выводом в память, а не с кешем.Если вы читаете один и тот же порт дважды, вы получаете разные ответы.Тем не менее, я бы согласился с вашей оценкой, что это более четко выражено в C # как атрибут.

С другой стороны, большинство фактических применений volatile в C # в любом случае можно лучше понимать как блокировку потока, поэтому выборof volatile is может быть немного неудачным.

Edit : Просто добавить: две ссылки, чтобы показать, что в C / C ++ `volatile это явно не для многопоточности.

...