2011-11-03 11 views
6

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.

+1

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

Respuesta

3

Sí, esto debería ser seguro y es uno de los usos previstos de la palabra clave volátil. Sin embargo, tenga en cuenta que no debe buclear simplemente para probar la condición; si simplemente desea esperar a que cambie, use una primitiva de sincronización adecuada para evitar perder el tiempo de la CPU. Tenga en cuenta también que esta técnica solo funciona porque solo tiene una escritura de subprocesos; Si varios subprocesos intentan incrementar el contador, puede perder aciertos (porque la lectura-modificación-escritura no es atómica).

+0

Creo que estos son buenos puntos para hacer. De lo que puedo deducir 'volátil' es realmente útil solo para casos simples como el anterior. Estoy aprendiendo que el multihilo de forma segura puede ser un esfuerzo bastante complicado. – Jeremy

Cuestiones relacionadas