C # - Действительно ли «volatile» действительно необходимо в качестве ключевого слова?

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

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

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

13
задан Ron Klein 21 August 2010 в 08:26
поделиться

5 ответов

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

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

2
ответ дан 1 December 2019 в 22:37
поделиться

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

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

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

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

5
ответ дан 1 December 2019 в 22:37
поделиться

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

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

8
ответ дан 1 December 2019 в 22:37
поделиться

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

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

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

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

4
ответ дан 1 December 2019 в 22:37
поделиться

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

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

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

2
ответ дан 1 December 2019 в 22:37
поделиться
Другие вопросы по тегам:

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