A look at CSharp Volatile Keyword

The other day the keyword Volatile came up in a discussion and I did not know the use of it.  So I figured, why not, let’s dig into it.

The volatile keyword can be put onto a field that may be accessed my multiple threads at the same time.  The effect of applying the fields with volatile is neat.  The compiler makes numerous optimizations and for fields reordering optimizations can take place.  When you apply the volatile keyword to the field declaration, compiler optimizations will not be applied to that field.

Take a look at the example below on declaring a public variable as volatile.

 private volatile bool _Stop;

Now let’s take that and put it into an application.  [more] The following example is based off of MSDN’s example.

public class WorkerClass
{
    // Called when a thread starts
    public void Working()
    {
        while (!_Stop)
        {
            Console.WriteLine("Worker thread: working...");
        }
        Console.WriteLine("Worker thread: terminating gracefully.");
    }

    public void RequestStop()
    {
        _Stop = true;
    }

    // Keyword volatile is used as a hint to the compiler that this data
    // member is accessed by multiple threads.
    private volatile bool _Stop;
}

public class WorkerThreadExample
{
    static void Main()
    {
        // Create the worker thread object.
        WorkerClass workerObject = new WorkerClass();
        Thread workerThread = new Thread(workerObject.Working);

        // Start the worker thread.
        workerThread.Start();
        Console.WriteLine("Main thread: starting worker thread...");

        // Loop until the worker thread activates.
        while (!workerThread.IsAlive)
        {
        }

        // Put the main thread to sleep for 1 millisecond to
        // allow the worker thread to do some work.
        Thread.Sleep(1);

        // Request that the worker thread stop itself.
        workerObject.RequestStop();

        // Use the Thread.Join method to block the current thread 
        // until the object's thread terminates.
        workerThread.Join();
        Console.WriteLine("Main thread: worker thread has terminated.");

        Console.ReadLine();
    }
    // Sample output:
    // Main thread: starting worker thread...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: working...
    // Worker thread: terminating gracefully.
    // Main thread: worker thread has terminated.
}

A lot of the explaining is done through the comments so I will save the reiteration of what has already been written.  Multithreading can cause some serious problems when they are executing at the same time.  By using the volatile keyword, it’s not causing synchronization of any parts, it’s instead telling the compiler to leave this field alone and not change the order of it.

Here is another example usage that may be a little easier on the eyes.

using System;
using System.Threading;
class Test
{
   public static int result;   
   public static volatile bool finished;
   static void Thread2() {
      result = 143;    
      finished = true; 
   }
   static void Main() {
      finished = false;
      // Run Thread2() in a new thread
      new Thread(new ThreadStart(Thread2)).Start();
      // Wait for Thread2 to signal that it has a result by setting
      // finished to true.
      for (;;) {
         if (finished) {
            Console.WriteLine("result = {0}", result);
            return;
         }
      }
   }
}

The main point to take from the second example is that with the finished variable set to volatile, it makes it impermissible for the store to result to be visible to the main thread before the store to finish.  If volatile is not used, it would be permissible for the main thread to see finished sooner and possible read the value of 0 from result.  Using volatile will ensure that this sort of ordering issues will not occur.  This does not take the place of the lock statement; it solely restricts some of the optimizations implemented by the compiler.


Leave a Reply

Your email address will not be published. Required fields are marked *

StackOverflow Profile