Как я могу установить минимальное значение в.Net без использования блокировки?

У меня есть несколько потоков доступа к переменным. Я знаю, как писать спин-блокировки и использовать методы Threading.Interlocked для увеличения и т. Д. Переменных.

Тем не менее, я хочу выполнить эквивалент:

a = Math.Min(a, b)
or
a = a | 10

... но без использования критического раздела. Это возможно? Я знаю, что вторая строка возможна в ассемблере, но нет метода Interlocked.Or.

2 ответа

Решение

Вот общая схема для имитации блокированной операции.

public static T InterlockedOperation<T>(ref T location, T value)
{
  T initial, computed;
  do
  {
    initial = location;
    computed = op(initial, value); // initial | value
  } 
  while (Interlocked.CompareExchange(ref location, computed, initial) != initial);
  return computed;
}

Операция min - это совсем другая история. Проблема в том, что в игре есть две области памяти. Кроме того, мы заинтересованы только в их чтении. Это означает, что нам действительно нужно беспокоиться только о проблеме с барьером памяти. Украсьте свои поля volatile или сделать явный вызов Thread.MemoryBarrier до вычисления мин.

Изменить: я пропустил тот факт, что результат операции мин назначается a, На самом деле вы можете использовать шаблон, который я определил выше, но вместо того, чтобы делать computed = initial | value делать computed = initial < value ? initial : value, Все остальное остается прежним.

Если вы не ожидаете много споров, то, возможно, что-то вроде этого? (Если может быть много споров, тогда простая блокировка вполне может быть более эффективной.)

int original;    // assuming here that a is an int
do
{
    original = a;
} while (Interlocked.CompareExchange(ref a, original | 10, original) != original)
Другие вопросы по тегам