Dekker算法混淆的变体

JK.*_*JK. 7 c# parallel-processing concurrency multithreading

这个程序执行两个不同的线程,并告诉我谁是"种族"的赢家.

出乎意料的是,有时两条线程"赢"(我预计有人或没有人获胜).这是预期的行为吗?为什么?我显然在这里缺少一些基本的东西.

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

A wins

B wins

A wins
B wins

A wins

...
Run Code Online (Sandbox Code Playgroud)

Lou*_*ann 3

您错误地使用了 挥发性:

将变量声明为 volatile 是不够的,您需要确保在读取/写入变量的任何地方都Thread.VolatileRead(ref myVar)使用/Thread.VolatileWrite(ref myVar)

此外,即使正确使用,易失性也不能确保读/写顺序(来自不同线程)。浏览 SO 以获取有关该主题的信息。编辑:它似乎在 x86 单核机器上执行

您可以简单地使用该lock声明,但如果您想了解真相,我建议您阅读、理解,然后再次阅读这本免费电子书

添加:
我刚刚浏览了Parallel.NET 4 中的类,没有volatile使用该关键字。由于某种原因,他们还会复制 before 循环
的数组,但我怀疑这会影响你。Action<T>