РЕДАКТИРОВАТЬ: вопрос в значительной степени переписан
Чтобы ответить на этот вопрос, я немного углубился в это дело и обнаружил несколько вещей о volatile
и Interlocked
, о которых мне не было известно. Давайте выясним это не только для меня, но и для этой дискуссии и для других людей, читающих об этом:
volatile
для чтения / записи должны быть защищены от переупорядочения. Это только означает чтение и запись, оно не означает любое другое действие;
- volatility не принудительно устанавливается на ЦП, т. Е. На аппаратном уровне (x86 использует ограждения получения и выпуска на любое чтение / запись). Это предотвращает оптимизацию компилятора или CLR;
Interlocked
использует атомарные инструкции по сборке для CompareExchange (cmpxchg
), Increment (inc
) и т. Д .;
Interlocked
иногда использует блокировку: аппаратная блокировка в многопроцессорных системах ; в однопроцессорных системах аппаратная блокировка отсутствует;
Interlocked
отличается от volatile
тем, что использует полный забор , где volatile использует половину забора.
- Чтение после записи может быть переупорядочено при использовании
volatile
. Это не может случиться с Interlocked
. VolatileRead
и VolatileWrite
имеют ту же проблему переупорядочения, что и `volatile (ссылка благодаря Брайану Гидеону).
Теперь, когда у нас есть правила, мы можем определить ответ на ваш вопрос:
- Технически: да, есть вещи, которые вы можете сделать с
volatile
, которые вы не можете сделать с Interlocked
:
- Синтаксис: вы не можете писать
a = b
, где a
или b
является изменчивым, но это очевидно;
- Вы можете прочитать другое значение после записи его в переменную переменной из-за переупорядочения. Вы не можете сделать это с
Interlocked
. Другими словами: вы можете быть менее безопасным с volatile
, тогда вы можете быть с Interlocked
.
- Производительность:
volatile
быстрее, чем Interlocked
.
Семантически: нет, потому что Interlocked
просто предоставляет расширенный набор операций и безопаснее в использовании, поскольку применяется полное ограждение. Вы не можете ничего сделать с volatile
, что вы не можете сделать с Interlocked
, и вы можете сделать много с Interlocked
, что вы не можете сделать с volatile:
static volatile int x = 0;
x++; // non-atomic
static int y = 0;
Interlocked.Increment(y); // atomic
Область действия: да, объявление переменной volatile
делает ее изменчивой для каждого отдельного доступа. Невозможно заставить это поведение другим способом, поэтому volatile
нельзя заменить на Interlocked
. Это необходимо в сценариях, где другие библиотеки, интерфейсы или оборудование могут обращаться к вашей переменной и обновлять ее в любое время, или требуется самая последняя версия.
Если вы спросите меня, этот последний бит действительно необходим для volatile
и может сделать его идеальным, когда два процесса совместно используют память и нуждаются в чтении или записи без блокировки. Объявление переменной как volatile
намного безопаснее в этом контексте, чем принуждение всех программистов использовать Interlocked
(что не может быть принудительно установлено компилятором).
РЕДАКТИРОВАТЬ: Следующая цитата была частью моего первоначального ответа, я оставлю его; -)
Цитата из языка программирования C # стандарт:
Для энергонезависимых полей, оптимизация
методы, которые считают, что порядок
инструкции могут привести к неожиданным
и непредсказуемые результаты в
многопоточные программы, которые получают доступ
поля без синхронизации, такие как
это предусмотрено оператором блокировки .
Эти оптимизации могут быть выполнены
компилятор, системой исполнения,
или аппаратно. Для летучих полей
такие переупорядочения оптимизации
ограничено:
Чтение летучего поля называется volatile read . Летучее чтение
имеет: приобретать семантику "; то есть
гарантированно произойдет до любого
ссылки на память, которые происходят после
это в последовательности команд.
Запись энергозависимого поля называется энергозависимая запись .
Летучая запись имеет «релиз»
семантика "; то есть это гарантированопроизойти после любых ссылок на память
до инструкции по записи в
последовательность команд.
Обновление: вопрос в значительной степени переписан, исправлен мой первоначальный ответ и добавлен "реальный" ответ