Подтвердить что ты не робот

Неустойчивость Нарушает свою основную работу?

Согласно MSDN:

Ключевое слово volatile указывает, что поле может быть изменено несколько потоков, которые выполняются в одно и то же время. Поля, которые объявленные volatile не подпадают под оптимизацию компилятора, что допускать доступ одним потоком. Это гарантирует, что большинство актуальное значение всегда присутствует в поле.

Обратите внимание на последнее предложение:

Это гарантирует, что самое актуальное значение всегда присутствует в поле.

Однако существует проблема с этим ключевым словом.

Я прочитал, что он может изменить порядок инструкций:

First instruction       Second instruction         Can they be swapped?
Read                         Read                         No
Read                         Write                        No
Write                       Write                         No 
Write                       Read                          Yes! <----

Это означает, что Джон устанавливает значение в поле volatile, а позже Пол хочет прочитать поле, Пол получает значение old!

Что здесь происходит? Разве это не главная работа?

Я знаю, что есть другие решения, но мой вопрос касается ключевого слова volatile.

Должен ли я (как программист) не использовать это ключевое слово - из-за такого странного поведения?

4b9b3361

Ответ 1

Документация MSDN неверна. Это, безусловно, не то, что делает volatile. Спецификация С# сообщает вам, что именно делает volatile, и получение "свежего чтения" или "совершенной записи" не является одним из них. Спецификация верна. volatile только гарантирует получение ограждений при чтении и выпуске записей при записи. Они определены ниже.

  • Захват: барьер памяти, в котором другие чтения и записи не могут перемещаться перед забором.
  • релиз-забор: барьер памяти, в котором другие чтения и записи не могут перемещаться после забора.

Я попытаюсь объяснить таблицу, используя обозначение стрелки. Стрелка ↓ будет отмечать изменчивое чтение, а стрелка ↑ будет отмечать неустойчивую запись. Никакая инструкция не может перемещаться по стрелке. Подумайте о том, как стрелка выталкивает все.

В следующем анализе я буду использовать переменные; x и y. Я также предполагаю, что они отмечены как volatile.

Случай №1

Обратите внимание, как размещение стрелки после считывания x предотвращает перемещение чтения y. Также обратите внимание, что волатильность y в данном случае не имеет значения.

var localx = x;
↓
var localy = y;
↓

Случай №2

Обратите внимание, как размещение стрелки после чтения x предотвращает перемещение записи в y. Также обратите внимание, что волатильность любого из x или y, но не обоих, могла быть опущена в этом случае.

var localx = x;
↓
↑
y = 1;

Случай №3

Обратите внимание, что размещение стрелки до записи до y предотвращает перемещение записи в x. Обратите внимание, что волатильность x в данном случае не имеет значения.

↑
x = 1;
↑
y = 2;

Дело № 4

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

↑
x = 1;
var localy = y;
↓

Известные номера

Также важно отметить, что:

  • Аппаратное обеспечение
  • x86 имеет волатильную семантику при записи.
  • Реализация Microsoft CLI (и подозрительная Mono также) имеет волатильную семантику при записи.
  • Спецификация ECMA не имеет волатильной семантики при записи.

Ответ 2

Ну, ты прав. Это более подробно описано в книге Джозефа Альбахари книга/статья.

В документации MSDN указано, что использование ключевого слова volatile гарантирует, что самое актуальное значение всегда присутствует в поле. Это неверно, поскольку, как видно, запись с последующим чтением может быть изменена.

http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword

Должен ли я (как программист) не использовать это ключевое слово - из-за такого странного поведения?

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

IMO, следует избегать использования ключевого слова volatile, так как вероятные ошибки трудно найти.

Ответ 3

Еще один момент, поднятый Джозефом Альбахари, заключается в том, что архитектура процесса может неблагоприятно влиять на изменчивость, т.е. AMD, в частности, может привести к изменению значений.

Так как вы, вероятно, не знаете, какой тип системы будет работать в вашем приложении, лучше всего избегать ключевого слова volatile.

Вы также должны избегать использования класса ReaderWriterLock при большой нагрузке на многопроцессорные системы, что позволяет одновременно использовать несколько блокировок записи здесь, которые будут вызывают зависание приложения, что будет чрезвычайно сложно вызвать причину