A continuación se muestra una implementación de un método entrelazado basado en Interlocked.CompareExchange
.
¿Es aconsejable que este código use un SpinWait
giro 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
}
Lo he visto SpinWait
usado en este escenario, pero mi teoría es que debería ser innecesario. Después de todo, el bucle solo contiene un puñado de instrucciones, y siempre hay un hilo que avanza.
Digamos que dos hilos están compitiendo para realizar este método, y el primer hilo tiene éxito de inmediato, mientras que el segundo hilo inicialmente no hace ningún cambio y tiene que reiterar. Sin otros contendientes, ¿es posible que el segundo hilo falle en su segundo intento ?
Si el segundo hilo del ejemplo no puede fallar en el segundo intento, ¿qué podríamos ganar con un SpinWait
? ¿Afeitarse algunos ciclos en el improbable caso de que cientos de hilos compitan para realizar el método?
SpinOnce
para evitar que un sistema operativo de un solo subproceso se vea potencialmente hambriento. Ver stackoverflow.com/questions/37799381/…
Interlocked
. Para aclarar, solo me interesa saber si a SpinWait
tiene sentido o no , por ejemplo, para ahorrar significativamente los ciclos de la CPU o (¡gracias @MatthewWatson!) Evitar que un sistema operativo de un solo subproceso se muera de hambre.
SpinWait
eso ni siquiera reduzca el consumo de energía, ya que de todos modos se realizará el mismo número de intentos. (Con dos hilos, ese es un intento para el primero y dos para el segundo hilo.)