He leído una buena cantidad de publicaciones sobre el tema, y creo que finalmente entiendo cómo funciona la palabra clave volatile
en C#. Aún así, quería preguntar aquí solo para asegurarme de que entiendo los conceptos correctamente. Considere el siguiente código: (¿o tal vez nunca)Uso de volátiles para la comunicación unidireccional entre hilos en .NET
class ThreadWrapper
{
public bool Enabled { get; set; }
private void ThreadMethod()
{
while (Enabled) { // ... Do work }
}
}
Por lo que entiendo, si otro hilo fuera a establecer Enabled=false
, el hilo original en realidad no puede ver este cambio de inmediato. Para asegurarse de que el compilador no optimice el acceso a la propiedad Enabled y dependa de los valores en caché, cambiar el código de la siguiente manera debería solucionarlo.
public bool Enabled { get {return mEnabled;} set {mEnabled=value;} }
private volatile bool mEnabled;
Ahora, cada vez que se lee el valor Habilitado, se garantiza que obtendrá su valor más actual, ¿correcto? Si es así, debería ser capaz de usarlo como una señal simple o una bandera (como la que tengo arriba).
Como otro ejemplo, considere lo siguiente:
class C
{
private volatile int i;
private volatile bool enabledA;
private volatile bool enabledB;
void ThreadA()
{
i = 0; // Reset counter
while (enabledA)
{
// .. Do some other repeated work
if (i > 100)
{
// .. Handle threshold case
}
}
}
void ThreadB()
{
while (enabledB)
{
// .. Do work
if (condition) // Some condition occurs that we want to count
{
i++;
}
}
}
}
Para sencilla la comunicación entre hilos de este tipo, es volatile
satisfactoria aquí? Entiendo que i++
no es una operación atómica, pero si un hilo está haciendo todo el incremento y otro simplemente quiere leerlo para ver si alcanza un cierto umbral, estamos bien ¿no?
Editar: Por supuesto que encontré another similar question with detailed answersdespués de el hecho.
Me encanta usar volátil para las instancias donde necesito una forma de marcar objeto por objeto y no quiero un bloqueo para cada objeto. Por ejemplo, algunas de mis aplicaciones que procesan por lotes tienen múltiples hilos que funcionan en objetos en una lista y un hilo que escribe en los objetos a medida que se completan. Acabo de hacer que los subprocesos de trabajo cambien un valor volátil cuando terminan con un objeto dado y el subproceso de escritor simplemente gira/duerme esperando ese valor mientras recorre la lista. – Bengie