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

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

Однако я хочу выполнить эквивалент:

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

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

Ответы [ 2 ]

2 голосов
/ 17 сентября 2010

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

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, прежде чем вычислять мин.

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

2 голосов
/ 17 сентября 2010

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

int original;    // assuming here that a is an int
do
{
    original = a;
} while (Interlocked.CompareExchange(ref a, original | 10, original) != original)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...