The optimization techniques used by the JIT (just-in-time) compiler in the Common Language Runtime might lead to unpredictable results when your .Net program is trying to perform non-volatile reads of data in a multithreaded scenario. In this article we’ll look at the differences between volatile and non-volatile memory access, the role of the volatile keyword in C#, and how the volatile keyword should be used.

I will provide some code examples in C# to illustrate the concepts. To understand how the volatile keyword works, first we need to understand how the JIT compiler optimization strategy works in .Net.

Understanding JIT compiler optimizations

It should be noted that the JIT compiler will, as part of an optimization strategy, change the order of the reads and writes in a way that does not change the meaning and eventual output of the program. This is illustrated in the code snippet given below.

x = 0;
x = 1;

The above snippet of code can be changed to the following—while preserving the program’s original semantics.