Abaixo está uma implementação de um método intertravado baseado em Interlocked.CompareExchange
.
É aconselhável que esse código use uma SpinWait
rotação antes de reiterar?
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
}
Eu já vi SpinWait
usado nesse cenário, mas minha teoria é que deveria ser desnecessário. Afinal, o loop contém apenas algumas instruções e sempre há um thread em progresso.
Digamos que dois threads estejam correndo para executar esse método, e o primeiro thread seja bem-sucedido imediatamente, enquanto o segundo thread inicialmente não faz alterações e precisa reiterar. Sem outros concorrentes, é possível que o segundo thread falhe em sua segunda tentativa ?
Se o segundo thread do exemplo não puder falhar na segunda tentativa, o que podemos ganhar com a SpinWait
? Eliminando alguns ciclos no caso improvável de centenas de threads correrem para executar o método?
SpinOnce
para impedir que um sistema operacional de thread único passe fome. Veja stackoverflow.com/questions/37799381/…
Interlocked
. Para esclarecimento, estou interessado apenas em saber se um SpinWait
é significativo ou não , por exemplo, para salvar significativamente os ciclos da CPU ou (obrigado @MatthewWatson!) Impedir que um sistema operacional de thread único passe fome.
SpinWait
isso não reduza o consumo de energia, pois o mesmo número de tentativas será realizado de qualquer maneira! (Com dois segmentos, que é uma tentativa para o primeiro e dois para o segundo segmento.)