Assume that we have the following code:
class Program
{
static volatile bool flag1;
static volatile bool flag2;
static volatile int val;
static void Main(string[] args)
{
for (int i = 0; i < 10000 * 10000; i++)
{
if (i % 500000 == 0)
{
Console.WriteLine("{0:#,0}",i);
}
flag1 = false;
flag2 = false;
val = 0;
Parallel.Invoke(A1, A2);
if (val == 0)
throw new Exception(string.Format("{0:#,0}: {1}, {2}", i, flag1, flag2));
}
}
static void A1()
{
flag2 = true;
if (flag1)
val = 1;
}
static void A2()
{
flag1 = true;
if (flag2)
val = 2;
}
}
}
It’s fault! The main quastion is Why… I suppose that CPU reorder operations with flag1 = true; and if(flag2) statement, but variables flag1 and flag2 marked as volatile fields…
In the .NET memory model, the runtime (CLI) will ensure that changes to volatile fields are not cached in registers, so a change on any thread is immediately seen on other threads (NB this is not true in other memory models, including Java’s).
But this says nothing about the relative ordering of operations across multiple, volatile or not, fields.
To provide a consistent ordering across multiple fields you need to use a lock (or a memory barrier, either explicitly or implicitly with one of the methods that include a memory barrier).
For more details see “Concurrent Programming on Windows”, Joe Duffy, AW, 2008