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

标签 c# parallel-processing x86 64-bit

    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。我不确定它是最大/最小还是临时值。当我改变时

static long x;

static int x;

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

最佳答案

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

在您的 32 位程序中,long(64 位)不会以原子方式写入。相反,它被写成两个 32 位 block 。同样,64 位值不会以原子方式读取,而是以两个 32 位片段的形式读取。

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

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


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

关于c# - 使用并行任务时x86和x64的数据类型有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30339797/

相关文章:

windows - 仅注入(inject)函数并通过 CreateRemoteThread 运行它? C++

C# MySql funktion(输入命令字符串,返回 reader)

c# - 将数据从一页发送到另一页

python - 与 z3 并行求解公式

java - java中如何使用ForkJoinPool来使用多核?

assembly - 定义全局描述符表有什么用?

c# - 如何获取xpath中的最后一张表?

c# - 反射类型加载异常

hadoop - 使用 Hadoop MapReduce 对字数进行排序

c++ - 我可以在多核 x86 CPU 上强制缓存一致性吗?