使用并行任务时 x86 和 x64 中的数据类型有什么区别

What is the difference between data type in x86 and x64 when using parallel task

    static long x;
    const int count = 1000000;

    static void ThreadProc()
    {
        for (int i = 0; i < count; ++i)
        {
            x = 0;
            var result = x;
            if (result != 0 && result != -1)
                Console.WriteLine("Opps 1");

        }
    }

    static void Main(string[] args)
    {
        var task = Task.Run(new Action(ThreadProc));

        for (int i = 0; i < count; ++i)
        {
            x = -1;
            var result = x;
            if (result != 0 && result != -1)
                Console.WriteLine("Opps 2");
        }

        task.Wait();
    }

此程序 运行 在 x64 中正确,但在 x86 中在 writeline 中显示文本。结果 var hold 值为 -4294967296 或 4294967296,x 仍为 0 或 -1。我不确定它是 max/min 还是临时值。当我改变

static long x;

static int x;

问题解决了。
我知道我们应该锁定 x 变量。但是我想知道为什么结果变量得到错误的值。

-4294967296 十进制是 0xffffffff00000000 作为 64 位十六进制。值 -1 十进制是 0xffffffffffffffff 作为 64 位十六进制。当然,值 00x0000000000000000。请注意,您看到的错误值是 -1 的一半和 0.

的一半

在您的 32 位程序中,long(即 64 位)不是自动写入的。相反,它被写成两个 32 位的片段。同样,64 位值不是原子读取的,而是分成两个 32 位的片段读取的。

有时,您显示的代码的一个线程会在写入过程中被另一个线程捕获。要么将两个 0x00000000 部分写入变量,要么将两个 0xffffffff 部分写入变量(取决于哪个线程被捕获)。任何一个非原子行为的线程都可能导致这种情况,但是当然 两个 线程都是非原子行为(写和读),所以根据每个线程在它们的竞争中的位置,你可以"blame" 两者都有问题。

当您将变量类型切换为 int 时,您将数据大小从 64 位更改为 32 位,这在 x86 程序中可以自动写入和读取。因此,两个线程都不会在写入或读取中被捕获。


见相关讨论: C# thread safe static member