con*_*ius 9 c++ multithreading memory-fences c++11
我正在尝试C++ 0x支持,并且存在一个问题,我想不应该存在.要么我不明白这个主题,要么gcc有一个bug.
我有以下代码,最初x
并且y
是相同的.线程1始终x
先递增,然后递增y
.两者都是原子整数值,因此根本没有增量问题.线程2正在检查是否x
小于y
,如果是,则显示错误消息.
这段代码有时会失败,但为什么呢?这里的问题可能是内存重新排序,但默认情况下所有原子操作都是顺序一致的,我没有明确放松那些操作.我正在x86上编译这段代码,据我所知,该代码不应该有任何订购问题.你能解释一下问题是什么吗?
#include <iostream>
#include <atomic>
#include <thread>
std::atomic_int x;
std::atomic_int y;
void f1()
{
while (true)
{
++x;
++y;
}
}
void f2()
{
while (true)
{
if (x < y)
{
std::cout << "error" << std::endl;
}
}
}
int main()
{
x = 0;
y = 0;
std::thread t1(f1);
std::thread t2(f2);
t1.join();
t2.join();
}
Run Code Online (Sandbox Code Playgroud)
结果可以在这里查看.
Jam*_*lis 12
比较存在问题:
x < y
Run Code Online (Sandbox Code Playgroud)
子表达式(在这种情况下,x
和y
)的评估顺序是未指定的,因此y
可以在之前评估x
或x
可以在之前评估y
.
如果x
先读取,则有问题:
x = 0; y = 0;
t2 reads x (value = 0);
t1 increments x; x = 1;
t1 increments y; y = 1;
t2 reads y (value = 1);
t2 compares x < y as 0 < 1; test succeeds!
Run Code Online (Sandbox Code Playgroud)
如果您明确确保y
首先阅读,则可以避免此问题:
int yval = y;
int xval = x;
if (xval < yval) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
Mic*_*urr 11
问题可能出在你的测试中:
if (x < y)
Run Code Online (Sandbox Code Playgroud)
线程可以评估x
,y
直到很久以后才开始评估.