Я прочитал много противоречивой информации (msdn, SO и т. Д.) О volatile и VoletileRead (ReadAcquireFence).
Я понимаю последствия этого ограничения переупорядочения доступа к памяти - что меня до сих пор полностью смущает, так это гарантия свежести, что для меня очень важно.
В msdn doc for volatile упоминается:
(...) Это гарантирует, что самое последнее значение всегда присутствует в поле.
msdn doc для изменчивых полей упоминает:
Чтение изменчивого поля называется изменчивым чтением. Неустойчивое чтение имеет «семантику получения»; то есть гарантируется, что это произойдет до любых обращений к памяти, которые происходят после него в последовательности команд.
public static int VolatileRead(ref int address)
{
int ret = address;
MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
return ret;
}
Согласно msdn MemoryBarrier doc Барьер памяти предотвращает переупорядочивание. Однако, похоже, это не влияет на свежесть - верно?
Как же тогда получить гарантию свежести? И есть ли разница между маркировкой поля volatile и доступом к нему с помощью семантики VolatileRead и VolatileWrite? В настоящее время я делаю последний критический для производительности код, который должен гарантировать свежесть, однако читатели иногда получают устаревшее значение. Мне интересно, изменит ли ситуацию маркировка состояния volatile.
РЕДАКТИРОВАТЬ1:
Чего я пытаюсь достичь - получить гарантию, что потоки читателей получат как можно более свежее значение общей переменной (записанное несколькими авторами) - в идеале не старше, чем стоимость переключения контекста или других операций, которые могут отложить немедленное выполнение. написать состояние.
Если у изменчивой конструкции или конструкции более высокого уровня (например, блокировки) есть эта гарантия (есть ли?), То как они этого достигают?
РЕДАКТИРОВАТЬ2:
Очень сжатый вопрос должен был звучать так: как мне получить гарантию получения максимально свежего значения во время чтения? В идеале без блокировки (поскольку монопольный доступ не требуется и существует вероятность высокой конкуренции).
Из того, что я здесь узнал, мне интересно, может ли это быть решением (строка решения (?) Отмечена комментарием):
private SharedState _sharedState;
private SpinLock _spinLock = new SpinLock(false);
public void Update(SharedState newValue)
{
bool lockTaken = false;
_spinLock.Enter(ref lockTaken);
_sharedState = newValue;
if (lockTaken)
{
_spinLock.Exit();
}
}
public SharedState GetFreshSharedState
{
get
{
Thread.MemoryBarrier(); // <---- This is added to give readers freshness guarantee
var value = _sharedState;
Thread.MemoryBarrier();
return value;
}
}
Вызов MemoryBarrier был добавлен, чтобы убедиться, что и чтение, и запись - закрыты полными ограждениями (так же, как код блокировки - как указано здесь http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword раздел« Барьеры памяти и блокировка »)
Выглядит правильно или ошибочно?
РЕДАКТИРОВАТЬ3:
Благодаря очень интересным обсуждениям здесь я узнал довольно много вещей и действительно смог перейти к упрощенному недвусмысленному вопросу, который у меня есть по этой теме. Он сильно отличается от исходного, поэтому я лучше разместил здесь новый: Барьер памяти против влияния блокировки на синхронизацию согласованности кешей памяти
GetFreshSharedState
? Вызывается ли он повторно в цикле? Вы можете разместить код? Он не обязательно должен быть полным или что-то в этом роде, могут быть полезны лишь некоторые фрагменты того, как он используется. - person Brian Gideon   schedule 10.07.2014