在使用并行任务时,x86和x64中的数据类型有什么不同?

本文关键字:数据类型 什么 x64 并行任务 x86 | 更新日期: 2023-09-27 17:49:45

    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保持值为-4294967296或4294967296,x仍然为0或-1。我不确定它是最大/最小或温度值。当我改变

static long x;

static int x;

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

在使用并行任务时,x86和x64中的数据类型有什么不同?

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

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

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

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


参见相关讨论:c#线程安全静态成员