This program execute two different threads and tell me who the winner of the “race” is.
Unexpectedly sometimes BOTH threads “wins” (I expected someone or no one to win). Is this expected behaviour and why? I’m obviously missing something fundamental here.
class Program
{
public volatile static int a = 0;
public volatile static int b = 0;
public static void Main()
{
for(int i = 0; i < 1000; i++)
{
a = 0;
b = 0;
Parallel.Invoke(delegate { a = 1; if (b == 0) Console.WriteLine("A wins"); },
delegate { b = 1; if (a == 0) Console.WriteLine("B wins"); });
Console.WriteLine(System.Environment.NewLine);
Thread.Sleep(500);
}
}
}
Results:
A wins
B wins
A wins
B wins
A wins
...
You’re using volatile incorrectly:
declaring the variables volatile is not enough, you need to make sure that everywhere you read/write them, you use
Thread.VolatileRead(ref myVar)/Thread.VolatileWrite(ref myVar)Also, volatile does NOT ensure read/write order (from different threads), even if used correctly. Browse SO for information on the topic. EDIT: it seems to do on a x86 single core machine
You could simply use the
lockstatement, but if you want to get to the bottom of this, I recommand reading, understanding, then reading again this free e-bookADDITIONS:
I just browsed through the
Parallelclass in .NET 4, and nowhere thevolatilekeyword is used.They also copy the array of
Action<T>before looping over it for some reason, but I doubt that impacts you.