C# Language volatile


Example

Adding the volatile keyword to a field indicates to the compiler that the field's value may be changed by multiple separate threads. The primary purpose of the volatile keyword is to prevent compiler optimizations that assume only single-threaded access. Using volatile ensures that the value of the field is the most recent value that is available, and the value is not subject to the caching that non-volatile values are.

It is good practice to mark every variable that may be used by multiple threads as volatile to prevent unexpected behavior due to behind-the-scenes optimizations. Consider the following code block:

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

In the above code-block, the compiler reads the statements x = 5 and y = x + 10 and determines that the value of y will always end up as 15. Thus, it will optimize the last statement as y = 15. However, the variable x is in fact a public field and the value of x may be modified at runtime through a different thread acting on this field separately. Now consider this modified code-block. Do note that the field x is now declared as 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);
    }    
}

Now, the compiler looks for read usages of the field x and ensures that the current value of the field is always retrieved. This ensures that even if multiple threads are reading and writing to this field, the current value of x is always retrieved.

volatile can only be used on fields within classes or structs. The following is not valid:

public void MyMethod()
{
    volatile int x;
}

volatile can only be applied to fields of following types:

  • reference types or generic type parameters known to be reference types
  • primitive types such as sbyte, byte, short, ushort, int, uint, char, float, and bool
  • enums types based on byte, sbyte, short, ushort, int or uint
  • IntPtr and UIntPtr

Remarks:

  • The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access.
  • The volatile keyword can be applied to fields of reference types
  • The volatile keyword will not make operating on 64-bit primitives on a 32-bit platform atomic. Interlocked operations such as Interlocked.Read and Interlocked.Exchange must still be used for safe multi-threaded access on these platforms.