c++ - 内存排序、指令重新排序和缺少 happens-before 关系

标签 c++ multithreading c++11

放宽顺序

标记为 std::memory_order_relaxed 的原子操作不是同步操作;只有每个单独的原子对象的修改顺序在线程之间共享。相对于其他线程,不同的对象之间没有顺序;可以看到操作乱序。

示例 – 宽松排序

#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<int> x{ 0 };
std::atomic<bool> x_is_set{ false };
std::atomic<int> counter{ 0 };
void f1()
{
    x.store(5, std::memory_order_relaxed);              // A
    x_is_set.store(true, std::memory_order_relaxed);    // B
}
void f2()
{
    while (!x_is_set.load(std::memory_order_relaxed));  // C

    if (x.load(std::memory_order_relaxed) == 5)         // D
        ++counter;                                      // E
}
int main()
{
    std::thread t1{ f1 };
    std::thread t2{ f2 };
    t1.join();
    t2.join();
    assert(counter.load() == 1);                        // F
}

线程 t1 和线程 t2 之间没有顺序约束。因此,在B完成的存储可以在A完成的存储之前被t2看到; main() 中的断言 F 将在这种情况下触发。

这个问题的明显解决方案是让 B 中的存储有 std::memory_order_release 并且 C 中的加载有 std::memory_order_acquire 用于同步目的。 F 中的断言似乎永远不会触发。

问题

但是,由于AB 之间没有happens-before 关系(我错了吗?),编译器不能/optimizer/CPU 重组函数 f1() 中的指令,使 B 先于 A?这将导致函数 f2() 中的 C 计算为 true,但 D 将为 false ;断言可能会触发。

有什么可以阻止该问题出现的吗?

最佳答案

since there is no happens-before relationship between A and B

错了。 [介绍.多线程]/p14:

An evaluation A happens before an evaluation B if:

  • A is sequenced before B, or
  • A inter-thread happens before B.

关于c++ - 内存排序、指令重新排序和缺少 happens-before 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32574459/

相关文章:

c++ - 为什么在 IUserNotificationCallback COM 对象上查询 IMarshall 接口(interface)?

Java 多线程 - 监视多个线程 Activity 的最佳方法是什么?

java - 如何在 Java 中实现非阻塞 Future

c++ - 为什么要使用完美转发的值(仿函数)?

c++ - constexpr 静态数据成员给出 undefined reference 错误

c++ - 在 Qt 中执行多个图形更改时如何最小化屏幕闪烁?

c++ - 使用 ISPC 编译器编译 OpenMP 程序

c++ - move : what does it take?

c++ - 如何开始编写智能指针?

java - 使用Firebase进行Android开发是否需要自己处理线程?