Ниже приведена реализация метода блокировки на основе Interlocked.CompareExchange
.
Желательно ли в этом коде использовать вращение SpinWait
перед повторением?
public static bool AddIfLessThan(ref int location, int value, int comparison)
{
int currentValue;
do
{
currentValue = location; // Read the current value
if (currentValue >= comparison) return false; // If "less than comparison" is NOT satisfied, return false
}
// Set to currentValue+value, iff still on currentValue; reiterate if not assigned
while (Interlocked.CompareExchange(ref location, currentValue + value, currentValue) != currentValue);
return true; // Assigned, so return true
}
Я видел SpinWait
, использованный в этом сценарии, но моя теория состоит в том, что это должно быть ненужным. В конце концов, цикл содержит только несколько инструкций, и всегда есть один поток, выполняющий прогресс.
Скажем, что два потока участвуют в гонке для выполнения этого метода, и первый поток сразу же завершается успешно, тогда как второй потокизначально не вносит изменений и должен повторить. Без других претендентов, возможно ли вообще потерпеть неудачу второму потоку во второй попытке ?
Если второй поток примера не может завершиться неудачей во второй попытке, то что мы можем получитьс SpinWait
? Срезать несколько циклов в маловероятном случае, когда сотня нитей мчится, чтобы выполнить метод?