c++ - 内存排序问题

标签 c++ multithreading c++11 memory-fences

我正在试验 C++0x 支持,但有一个问题,我想它不应该存在。要么我不明白主题,要么 gcc 有错误。

我有以下代码,最初 xy 是相等的。线程 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();
}

可以查看结果here .

最佳答案

比较有问题:

x < y

子表达式(在本例中为 xy)的求值顺序未指定,因此 y 可以在 xx 可以在 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!

如果您明确确保首先读取y,则可以避免该问题:

int yval = y;
int xval = x;
if (xval < yval) { /* ... */ }

关于c++ - 内存排序问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4012092/

相关文章:

c++ - 制作分组框按钮 win32 C++

java - 我正在尝试使用线程在小程序中移动球,但它没有移动

c++ - [=] 是否暗示将复制所有局部变量?

c++ - 委托(delegate)构造函数抛出时是否调用析构函数?

c++ - 关键部分或互斥体应该是真正的成员变量还是什么时候应该是?

c++ - Qt 5 的模型测试?

android - 应用程序停止后线程仍在运行

c++ - 在模板中有没有办法为每个计时实例只编写一个特化? (纳秒、毫秒、秒等)

c++ - 带 Boost Spirit X3 的最小计算器

c - 共享内存环境的 C 互斥实现