Labels

Monday, June 15, 2009

Threading || Volatile

Volatile

 

Common usage of the volatile modifier is when a particular field is accessed by many threads without using the lock statement to serialize access.

So in essence the volatile modifier guarantees that a thread will retrieve the most recent value written by another thread (even if it was modified by the previous instruction from where you called).

 

Whenever a volatile is requested, the system returns the current value at the time of the request.

Similarly, All assignments are written to the object immediately.

 

You are not allowed to use volatile on just any time. The following is a list of types you can implement this modifier on:

 

  • Any reference type.
  • Any pointer type in a unsafe context
  • sbyte, byte, short, ushort, int, uint, char, float, bool.
  • An enum type with an enum base type of the following: byte, sbyte, short, ushort, int, uint.

 

 

 

public volatile int iAge;

 

 

 

Another Important Example

 

 

class Unsafe

    {

        static bool endIsNigh = false;

        static bool repented = false;

 

        static void Main()

        {

            new Thread(Wait).Start(); // Start up the spinning waiter

            Thread.Sleep(1000); // Give it a second to warm up!

 

            repented = true;

            endIsNigh = true;

            Console.WriteLine("Going...");

        }

 

        static void Wait()

        {

            while (!endIsNigh)

            {

                 // Keep Spinning

            }

            Console.WriteLine("Gone, " + repented);

        }

    }

 

Let’s understand the usage of ‘Volatile’ by this example. Consider two possiblilities from the above example.

 

  1. Is it possible for the Wait method to continue spinning in its while loop, even after the endIsNigh flag has been set to true?
  2. Furthermore, is it possible for the Wait method to write "Gone, false"?

 

The answer to both questions is, theoretically, yes, on a multi-processor machine, if the thread scheduler assigns the two threads different CPUs.

The repented and endIsNigh fields can be cached in CPU registers to improve performance, with a potential delay before their updated values are written back to memory.

And when the CPU registers are  written back to memory, it’s not necessarily in the order they were originally updated. This can result in two scenarios possible.

 

This caching can be circumvented by using the static methods Thread.VolatileRead and Thread.VolatileWrite to read and write to the fields. VolatileRead means “read the latest value”; VolatileWrite means “write immediately to memory”. The same functionality can be achieved more elegantly by declaring the field with the volatile modifier.

 

 

 

class Unsafe

    {

        volatilestatic bool endIsNigh = false;

        volatile static bool repented = false;

 

       // Same code as above

    }

 

 

 

 

Hope this helps.

 

Thanks & Regards,

Arun Manglick || Senior Tech Lead

 

 

No comments:

Post a Comment