C# Language volátil


Ejemplo

Agregar la palabra clave volatile a un campo indica al compilador que el valor del campo puede ser cambiado por varios subprocesos separados. El propósito principal de la palabra clave volatile es evitar las optimizaciones del compilador que asumen solo el acceso de un solo hilo. El uso de volatile garantiza que el valor del campo sea el valor más reciente disponible, y que el valor no esté sujeto al almacenamiento en caché que tienen los valores no volátiles.

Es una buena práctica marcar cada variable que puede ser utilizada por múltiples subprocesos como volatile para evitar comportamientos inesperados debido a optimizaciones detrás de escena. Considere el siguiente bloque de código:

public class Example
{
    public int x;

    public void DoStuff()
    {
        x = 5;

        // the compiler will optimize this to y = 15
        var y = x + 10;

        /* the value of x will always be the current value, but y will always be "15" */
        Debug.WriteLine("x = " + x + ", y = " + y);
    }    
}

En el bloque de código anterior, el compilador lee las declaraciones x = 5 y y = x + 10 y determina que el valor de y siempre terminará como 15. Por lo tanto, optimizará la última instrucción como y = 15 . Sin embargo, la variable x es de hecho un campo public y el valor de x se puede modificar en tiempo de ejecución a través de un hilo diferente que actúa en este campo por separado. Ahora considere este código de bloque modificado. Tenga en cuenta que el campo x ahora se declara como volatile .

public class Example
{
    public volatile int x;

    public void DoStuff()
    {
        x = 5;

        // the compiler no longer optimizes this statement
        var y = x + 10;

        /* the value of x and y will always be the correct values */
        Debug.WriteLine("x = " + x + ", y = " + y);
    }    
}

Ahora, el compilador busca los usos de lectura del campo x y asegura que el valor actual del campo siempre se recupera. Esto asegura que incluso si varios subprocesos están leyendo y escribiendo en este campo, el valor actual de x siempre se recupera.

volatile solo puede usarse en campos dentro de las class o struct . Lo siguiente no es válido :

public void MyMethod()
{
    volatile int x;
}

volatile solo puede aplicarse a campos de los siguientes tipos:

  • tipos de referencia o parámetros de tipo genérico conocidos como tipos de referencia
  • tipos primitivos como sbyte , byte , short , ushort , int , uint , char , float y bool
  • enums tipos basados ​​en byte , sbyte , short , ushort , int o uint
  • IntPtr y UIntPtr

Observaciones:

  • El modificador volatile se usa generalmente para un campo al que se accede mediante varios subprocesos sin usar la instrucción de bloqueo para serializar el acceso.
  • La palabra clave volatile se puede aplicar a campos de tipos de referencia
  • La palabra clave volatile no funcionará con primitivos de 64 bits en una plataforma atómica de 32 bits. Las operaciones interbloqueadas, como Interlocked.Read y Interlocked.Exchange , todavía deben usarse para el acceso seguro de múltiples subprocesos en estas plataformas.