Как я могу установить минимальное значение в.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)