C# Language volatile


Esempio

L'aggiunta della parola chiave volatile a un campo indica al compilatore che il valore del campo può essere modificato da più thread separati. Lo scopo principale della parola chiave volatile è impedire le ottimizzazioni del compilatore che presuppongono solo l'accesso a thread singolo. L'utilizzo di volatile garantisce che il valore del campo sia il valore più recente disponibile e che il valore non sia soggetto alla memorizzazione nella cache dei valori non volatili.

È buona norma contrassegnare tutte le variabili che possono essere utilizzate da più thread come volatile per prevenire comportamenti imprevisti a causa di ottimizzazioni dietro le quinte. Considera il seguente blocco di codice:

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);
    }    
}

Nel suddetto codice, il compilatore legge le istruzioni x = 5 y = x + 10 e determina che il valore di y finirà sempre per 15. Quindi, ottimizzerà l'ultima istruzione come y = 15 . Tuttavia, la variabile x è in realtà un campo public e il valore di x può essere modificato in fase di esecuzione attraverso un thread diverso che agisce su questo campo separatamente. Ora considera questo blocco di codice modificato. Si noti che il campo x è ora dichiarato come 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);
    }    
}

Ora, il compilatore cerca gli usi di lettura del campo x e assicura che il valore corrente del campo sia sempre recuperato. Ciò garantisce che anche se più thread stanno leggendo e scrivendo in questo campo, il valore corrente di x viene sempre recuperato.

volatile può essere utilizzato solo su campi all'interno di class o struct . Quanto segue non è valido :

public void MyMethod()
{
    volatile int x;
}

volatile può essere applicato solo ai campi dei seguenti tipi:

  • tipi di riferimento o parametri di tipo generico noti per essere tipi di riferimento
  • tipi primitivi come sbyte , byte , short , ushort , int , uint , char , float e bool
  • tipi di enumerazione basati su byte , sbyte , short , ushort , int o uint
  • IntPtr e UIntPtr

Osservazioni:

  • Il modificatore volatile viene in genere utilizzato per un campo a cui si accede da più thread senza utilizzare l'istruzione lock per serializzare l'accesso.
  • La parola chiave volatile può essere applicata a campi di tipi di riferimento
  • La parola chiave volatile non renderà operativo su primitive a 64 bit su una piattaforma atomica a 32 bit. Le operazioni interbloccate come Interlocked.Read e Interlocked.Exchange devono ancora essere utilizzate per un accesso multi-thread sicuro su queste piattaforme.