Хотя не строго основанный на программировании, я наслаждался много Одиссея Робота , игра, где Вы соединили логические элементы проводом к датчикам и двигателям в роботе, чтобы заставить ее переместиться и реагировать на среду, выйти из города, выйдя из препятствий. Я играл в на Apple//e, это была одна из лучших игр на этом компьютере (с Бегуном Кладезя!:-)).
РЕДАКТИРОВАТЬ: вопрос в значительной степени переписан
Чтобы ответить на этот вопрос, я немного углубился в вопрос и узнал кое-что о volatile
и Interlocked
, о котором я не знал. Давайте проясним это не только для меня, но и для этого обсуждения и других людей, читающих об этом:
volatile
чтение / запись должны быть невосприимчивы к переупорядочению. Это только означает чтение и запись, оно не означает какое-либо другое действие; Interlocked
использует атомарные инструкции сборки для CompareExchange ( cmpxchg
), Приращение ( inc
) и т.д .; Interlocked
иногда использует блокировку: аппаратная блокировка в многопроцессорных системах ; в однопроцессорных системах аппаратная блокировка отсутствует; Interlocked
отличается от volatile
тем, что он использует полное ограждение , где volatile использует половинное ограждение. энергозависимого
. Этого не может случиться с Interlocked
. VolatileRead
и VolatileWrite
имеют ту же проблему переупорядочения, что и `volatile (ссылка благодаря Брайану Гидеону). Теперь, когда у нас есть правила, мы можем дать ответ на ваш вопрос:
a = b
, где a
или b
является непостоянным, но это очевидно; Interlocked
. Другими словами: вы можете быть менее безопасным с volatile
, тогда вы можете быть с Interlocked
. volatile
быстрее затем Interlocked
. Семантически: нет, потому что Interlocked
просто предоставляет расширенный набор операций и его безопаснее использовать, потому что он применяет полное ограждение. Вы можете'
x ++; // неатомный
статический int y = 0;
Interlocked.Increment (y); // атомарный
Область действия: да, объявление переменной volatile
делает ее изменчивой для каждого отдельного доступа. Невозможно заставить это поведение каким-либо другим способом, поэтому volatile
не может быть заменен на Interlocked
. Это необходимо в сценариях, когда другие библиотеки, интерфейсы или оборудование могут получить доступ к вашей переменной и обновить ее в любое время, или если вам нужна самая последняя версия.
Если вы спросите меня, этот последний бит является реальной потребностью в volatile
и может сделать его идеальным, когда два процесса совместно используют память и должны читать или писать без блокировки. Объявление переменной как volatile
намного безопаснее в этом контексте, чем принуждение всех программистов использовать Interlocked
(что вы не можете заставить компилятор).
EDIT: следующая цитата была частью моего первоначального ответа, я методы, которые считают, что переупорядочить инструкции могут привести к неожиданным и непредсказуемые результаты в многопоточные программы, которые обращаются к поля без синхронизации, такие как что предусмотрено оператором блокировки . Эти оптимизации могут быть выполнены компилятор исполняющей системой, или аппаратно. Для нестабильных полей такие оптимизации переупорядочения ограничено:
Чтение изменчивого поля называется изменчивым чтением . Неустойчивое чтение имеет: приобретать семантику ", то есть гарантированно произойдет до любого ссылки на память, которые появляются после это в последовательности команд.
Запись энергозависимого поля называется энергозависимой записью . А летучая запись имеет "выпуск" семантика ", то есть гарантировано происходить после любых обращений к памяти до инструкции записи в последовательность инструкций.
Обновление: вопрос в значительной степени переписан, исправлен мой исходный ответ и добавлен «настоящий» ответ
Да - вы можете посмотреть значение напрямую.
Если вы ТОЛЬКО используете Блокированный класс для доступа к переменной, тогда нет никакой разницы. Что делает volatile , так это то, что он сообщает компилятору, что переменная является особенной, и при оптимизации не следует предполагать, что значение не изменилось.
Использует этот цикл:
bool done = false;
...
while(!done)
{
... do stuff which the compiler can prove doesn't touch done...
}
Если вы установите ] done
to true
в другом потоке вы ожидаете выхода из цикла. Однако - если done не помечено как volatile
, то у компилятора есть возможность понять, что код цикла никогда не может измениться done
, и он может оптимизировать сравнение для выхода.
Я не буду пытаться быть авторитетом по этой теме, но я настоятельно рекомендую вам ознакомиться с этой статьей хваленым Джоном Скитом.
Также взгляните на заключительную часть этого ответа , в которой подробно описывается для чего следует использовать volatile
.
Да, вы можете повысить производительность, используя изменчивую переменную вместо блокировки.
Блокировка - это полный барьер памяти, который может дать вам те же характеристики, что и у изменчивой переменной, а также многие другие. Как уже было сказано, volatile просто гарантирует, что в многопоточных сценариях, если ЦП изменяет значение в своей строке кэша, другие ЦП сразу видят это значение, но не гарантируют никакой семантики блокировки вообще.
Дело в блокировке. намного более мощный, чем volatile, и вы должны использовать volatile, когда это возможно, чтобы избежать ненужных блокировок.
Это довольно сложная тема. Я считаю, что статья Джозефа Альбахари является одним из наиболее исчерпывающих и точных источников концепций многопоточности в .NET Framework, которые могут помочь ответить на ваш вопрос.
Но, чтобы быстро резюмировать, есть много совпадений. между ключевым словом volatile
и классом Interlocked
, насколько они могут быть использованы. И, конечно же, и то, и другое выходит за рамки того, что вы можете сделать с обычной переменной.