“volatile” – 1: C#

Volatile constructs are primitive thread synchronization constructs in the .Net platform. The main usage of them can be listed as:
  1. Disable the optimisation intended for single threaded applications, which most of the compilers assume. Meaning, they are flags for the compilers instructing them not to optimize the code according to the single threading.
  2. Disable caching in hardware, either in a thread variable or in a CPU register.
  3. Behave as a memory barrier construct (this will be explained later in this article).
1-Disabling the Optimisations
(to make the optimisations work, compile your code with “/platform:x86″  and “/optimize+” switches)
Take a look at the following code (taken from “CLR Via C#” 3rd Edition, Jeffrey Richter)
private static void OptimizedAway() { 
   // Constant expression is computed at compile time resulting in zero  
   Int32 value = (1 * 100) – (50 * 2);  
   // If value is 0, the loop never executes 
   for (Int32 x = 0; x < value; x++) {  
       // There is no need to compile the code in the loop since it can never execute 
      Console.WriteLine(“Jeff”); 
   } 
}
Compiler will see
Int32 value = (1 * 100) – (50 * 2);  
and will convert this to
Int32 value = 0;
and because the value is zero, then the “for” statement will not work, so the compiler will remove the code (optimize away).
There may be many situations like this. To tell the compiler no to implement this one must define the variable “value” “volatile“.
2-Disable the Caching
When a variable is declared to be volatile, when ever its value is read or written, it will be done via the main memory. So the caching mechanism will be disabled, i.e., the CPU registers. It will be the up-to-date fresh value from the real place it resides, the main memory. Because of this, volatile fields are slow in respect to other type of variable access.
3-Behave as a Memory Barrier
volatile” keyword, in C#, is a shorthand for Thread’s “VolatileWrite” and “VolatileRead” methods.
Compilers (even CPU) can order the execution of a program different than the one indicated by the programmer. This is OK in most situations or in a single threaded application. But in some situation, you need your codes to be executed in the same order you entered. This is where a memory barrier comes in to the picture. Let us see by examples:
[Wikipedia Sample]
Processor #1:
 while f == 0
  ;
 //A- Memory Barrier required here
 print x;
Processor #2:
 x = 42;
 //B- Memory Barrier required here
 f = 1;
if any of the operations are executed out of the order by the compiler or by the CPU, then the result will be quite unexpected. To disable this, memory barrier should be used.
In C# three constructs provides this feature and they are
public sealed class Thread {  
   public static  void  VolatileWrite(ref  Int32 address,  Int32 value);   
   public static  Int32 VolatileRead(ref  Int32 address);  
   public static  void  MemoryBarrier(); 
}
a-Thread.VolatileWrite
In the above example, if I write Thread.VolatileWrite in places indicated, I would ensure that, this code (Thread.VolatileWrite) will work in the place I intended to. And any operations that I wrote before will work before this code (Thread.VolatileWrite). But the operations written before does not necessarily must be in the same order I have written them.
b-Thread.VolatileRead
It is similar to write construct with only one difference. This is a read construct and the operations after that will execute after the code (Thread.VolatileRead). Still, Thread.VolatileRead will execute at the point where I intended it.
c-MemoryBarrier
It is somewhat the combination of the two above mentioned methods. It does not read or write any variables but it will execute at the same point the program intended and the calls before it will work before it and the calls after it will work after it.

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>