使用并行任务时 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 位十六进制。当然,值 0
是 0x0000000000000000
。请注意,您看到的错误值是 -1
的一半和 0
.
的一半
在您的 32 位程序中,long
(即 64 位)不是自动写入的。相反,它被写成两个 32 位的片段。同样,64 位值不是原子读取的,而是分成两个 32 位的片段读取的。
有时,您显示的代码的一个线程会在写入过程中被另一个线程捕获。要么将两个 0x00000000
部分写入变量,要么将两个 0xffffffff
部分写入变量(取决于哪个线程被捕获)。任何一个非原子行为的线程都可能导致这种情况,但是当然 两个 线程都是非原子行为(写和读),所以根据每个线程在它们的竞争中的位置,你可以"blame" 两者都有问题。
当您将变量类型切换为 int
时,您将数据大小从 64 位更改为 32 位,这在 x86 程序中可以自动写入和读取。因此,两个线程都不会在写入或读取中被捕获。
见相关讨论:
C# thread safe static member
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 位十六进制。当然,值 0
是 0x0000000000000000
。请注意,您看到的错误值是 -1
的一半和 0
.
在您的 32 位程序中,long
(即 64 位)不是自动写入的。相反,它被写成两个 32 位的片段。同样,64 位值不是原子读取的,而是分成两个 32 位的片段读取的。
有时,您显示的代码的一个线程会在写入过程中被另一个线程捕获。要么将两个 0x00000000
部分写入变量,要么将两个 0xffffffff
部分写入变量(取决于哪个线程被捕获)。任何一个非原子行为的线程都可能导致这种情况,但是当然 两个 线程都是非原子行为(写和读),所以根据每个线程在它们的竞争中的位置,你可以"blame" 两者都有问题。
当您将变量类型切换为 int
时,您将数据大小从 64 位更改为 32 位,这在 x86 程序中可以自动写入和读取。因此,两个线程都不会在写入或读取中被捕获。
见相关讨论:
C# thread safe static member