我在多线程编程方面陷入了一团混乱,希望有人能够来帮我理解一下。
在阅读了很多资料后,我明白了在64位系统上应该能够原子地设置64位int类型的值1。
但是,对于这些资料中的很多内容我感到困惑,所以我尝试编写一个简单的程序来验证。我编写了一个只有一个线程的简单程序,该程序将变量设置为两个值中的一个:
bool switcher = false;
while(true)
{
if (switcher)
foo = a;
else
foo = b;
switcher = !switcher;
}
还有一个线程会检查 foo
的值:
while (true)
{
__uint64_t blah = foo;
if ((blah != a) && (blah != b))
{
cout << "Not atomic! " << blah << endl;
}
}
我设置了 a = 1844674407370955161;
和 b = 1144644202170355111;
。运行程序后,没有任何输出警告我 blah
不是 a
或 b
。
看起来很好,似乎这是一个原子写操作...但是,接下来我改变了第一个线程直接设置 a
和 b
,代码如下:
bool switcher = false;
while(true)
{
if (switcher)
foo = 1844674407370955161;
else
foo = 1144644202170355111;
switcher = !switcher;
}
我重新运行,突然出现:
Not atomic! 1144644203261303193
Not atomic! 1844674406280007079
Not atomic! 1144644203261303193
Not atomic! 1844674406280007079
什么改变了?无论如何,我都给foo
赋了一个很大的数字 - 编译器是否会以不同的方式处理常数,或者我误解了一切?谢谢!
1:Intel CPU文档,第8.1节,保证原子操作 2:GCC开发人员讨论GCC在文档中没有保证,但内核和其他程序依赖它