在使用并行任务时,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。但是我想知道为什么结果变量得到错误的值。
-4294967296
的十进制值为0xffffffff00000000
的64位十六进制。-1
的十进制表示0xffffffffffffffff
,为64位十六进制。当然0
的值是0x0000000000000000
。请注意,您看到的错误值是-1
的一半和0
的一半。
在32位程序中,long
(64位)不会被自动写入。相反,它被写成两个32位块。同样,64位的值不会自动读取,而是分成两个32位的片段读取。
有时,您所展示的代码的一个线程会在写入过程中被另一个线程捕获。要么将两个0x00000000
部分写入变量,要么将两个0xffffffff
部分写入变量(取决于哪个线程被捕获)。任何一个线程的非原子行为都可能导致这种情况,但是当然两个线程的行为都是非原子的(写和读),因此根据每个线程在其竞争中的位置,您可以将问题"归咎于"其中任何一个。
当您将变量类型切换为int
时,您将数据大小从64位更改为32位,这在x86程序中可以自动写入和读取。因此,两个线程都不能在写入或读取过程中被捕获。
参见相关讨论:c#线程安全静态成员