Барьер памяти или блокировка перед возвратом _counter; необходимо
Да, абсолютно. Рассмотрим следующий код.
while (foo.Counter == 0)
{
// Do something
}
Проблема в том, что если содержимое внутри цикла достаточно простое, то компилятор C #, JIT или аппаратное обеспечение будут оптимизировать код таким образом.
int register = foo._counter;
while (register == 0)
{
// Do something
}
Или даже это.
if (foo._counter == 0)
{
START:
// Do something
goto START;
}
Обратите внимание, что я использую _counter
вместо Counter
, чтобы предположить, что свойство, вероятно, будет встроенным. Затем, что более важно, JIT-компилятор может «поднять» чтение _counter
за пределы цикла, чтобы оно читалось только один раз.
Барьеры памяти не дают гарантии свежести как таковые. Они предотвращают определенные программные или аппаратные оптимизации, которые изменяют порядок чтения и записи в память. гарантия свежести - это скорее побочный эффект.
Итак, чтобы обернуть вещи, ваше свойство Counter
должно выглядеть следующим образом.
public int Counter
{
get { return Interlocked.CompareExchange(ref _counter, 0, 0); }
}