Я прочитал много противоречащей информации (msdn, SO и т.д.) об изменчивости и VoletileRead (ReadAcquireFence).
Я понимаю, что ограничение доступа к реорганизации доступа к памяти - это то, что я до сих пор полностью смущен, - это гарантия свежести, что очень важно для меня.
msdn doc для 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 Предел памяти препятствует переупорядочению. Однако, похоже, это не влияет на свежесть - правильно?
Как тогда можно получить гарантию свежести? И разве разница между полем маркировки изменчивым и доступ к нему с помощью семантики VolatileRead и VolatileWrite? В настоящее время я делаю последнее в своем критическом критическом коде, которое должно гарантировать свежесть, однако читатели иногда получают устаревшее значение. Мне интересно, изменит ли положение состояние волатильность ситуации.
EDIT1:
То, что я пытаюсь достичь, - получить гарантию того, что потоки чтения получат как последнее значение общей переменной (написанной несколькими писателями), насколько это возможно - в идеале не старше, чем стоимость переключения контекста или других операций, которые могут отложить немедленную запись состояния.
Если эта энергозависимая или более строгая конструкция (например, блокировка) имеет эту гарантию (они?), чем они достигают этого?
EDIT2:
Очень сжатый вопрос должен был быть как мне получить гарантию как свежую ценность при чтении как можно? В идеале без блокировки (поскольку эксклюзивный доступ не нужен, и есть вероятность высокой конкуренции).
Из того, что я узнал здесь, мне интересно, может ли это быть решением (строка решения (?) помечена комментарием):
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 "Разделение памяти и блокировка" )
Означает ли это, что это правильно или оно испорчено?
EDIT3:
Благодаря очень интересным дискуссиям здесь я узнал немало вещей, и я действительно смог перейти к упрощенному недвусмысленному вопросу, который у меня есть об этой теме. Это сильно отличается от оригинального, поэтому я скорее разместил здесь новый: Защитный барьер против блокированного воздействия на таймер синхронизации кэшей памяти