c++ - as-if 规则是否会阻止编译器对全局/成员变量的访问进行重新排序?

标签 c++ multithreading c++11

我正在研究编译器优化(特别是此处的指令重新排序)可能对多线程程序产生的影响。

假设我们有一个读者线程和一个作者线程。

// Global shared data between threads
bool data;
bool flag = false;

// writer.cpp
void writer()
{
    data = true;  // (1)
    flag = true;  // (2)
}

// reader.cpp
void reader()
{
    if (flag)
    {
       count << data;
    }
}

兼容 C++11 的编译器可以重新排序指令 (1)(2) 吗?

根据 C++ 的“as-if”规则,转换不应改变程序的可观察行为。显然,在编译 writer 时,编译器通常不能确定重新排序 (1)(2) 是否会改变程序的可观察行为,因为 dataflag 都是全局变量,可能会影响另一个线程的可观察行为。

但它在这里声明这种重新排序可能会发生,请参阅 memory ordering at compile time .

那么我们是否需要在 (1)(2) 之间设置编译器屏障? (我很清楚可能的 CPU 重新排序。这个问题只针对编译器重新排序)

最佳答案

当然可以。编译器没有义务考虑对其他线程或硬件的副作用。

只有在您使用 volatile 或同步(这两者不可可互换)时,编译器才会被迫考虑这一点。

标准内存模型称为 SC-DRF,即无顺序一致数据竞争。数据竞争正是您刚刚描述的场景——一个线程正在观察非同步变量,而另一个线程正在改变它们。这是未定义的行为。实际上,该标准明确地赋予编译器自由假设没有其他线程或硬件正在读取非 volatile 非同步变量。编译器在此基础上进行优化是绝对合法的。

顺便说一句,那个链接有点垃圾。他的“修复”根本没有解决任何问题。多线程代码的唯一正确解决方法是使用同步。

关于c++ - as-if 规则是否会阻止编译器对全局/成员变量的访问进行重新排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25472608/

相关文章:

python - 为什么多线程和单线程没有执行时间差异

c++ - 多处理器 boost::线程?在一个处理器上运行的所有线程

c++ - uninit_member : Non-static class member m_wszParams is not initialized in this constructor nor in any functions that it calls in C++

c++ - BFS 路径 C++ 实现返回返回一个额外的值

javascript - 如何使用带有输入和输出参数的 Javascript 制作良好的 API 集?

c++ - 在 C++ 中模拟 C# 索引器

java - 使用 AtomicReference 对多个预期值进行比较和设置

c++ - 在多个共享库中静态库成员的多重初始化

c++ - Unreal - 在 cpp 中创建对象时如何避免硬编码路径

c++ - 在 C++0x 中是否有类似 static_assert 的东西给出警告而不是错误?