【问题标题】:宽松的内存模型可以在同一个线程上重新排序吗?
【发布时间】:2022-01-23 06:26:55
【问题描述】:

我想知道,memory_order_relaxed 是否允许在同一个线程上不受约束地重新排序代码?例如:

// All on the same thread
std::atomic_int num(10);

std::cout << num.load(memory_order_relaxed) << "\n";
num.store(0, memory_order_relaxed);

是否可以打印 0? (在实际代码中另一个线程正在修改num,但它无关)

【问题讨论】:

  • 如果没有其他线程正在修改它,则排序不会有任何区别。只有两个线程同时对同一事物进行操作,顺序才是重要的。
  • @DavidSchwartz 哦,好的。所以在这个例子中,不可能打印 0,对吧?
  • 没有。并且操作发生的顺序并不重要,因为没有其他线程在观察它们。也许 0 的写入是在加载执行之前被发送到内存的,但是你怎么知道呢?没有人在看那个。
  • Maybe the write of 0 is emitted to memory before the load is executed, but how could you tell 等等,这可能吗?
  • 有可能,但你永远无法判断。没有人观察到这种行为。

标签: c++ multithreading atomic


【解决方案1】:

“重新排序”不是考虑多线程代码的有用方式,因为它太不精确了。相反,我们应该注意以下几点:

  • 每个线程按顺序执行。
  • 程序中的每个原子变量都有一个修改顺序,所有线程都同意
  • 不同原子变量的修改没有单一顺序(除非此类原子变量仅通过顺序一致的操作访问)。
  • 一个线程可能不会观察到由另一个线程修改的两个不同原子变量的副作用,这些原子变量的修改顺序与实际发生修改的顺序相同。例如,线程 1 可以修改原子变量a,然后修改原子变量b。线程 2 可能会观察到 b 的新值,然后是 a 的旧值。这就是大多数人认为的“重新排序”。

在您的问题中,答案是否定的,不能打印 0。这是由于上面的第一条规则:每个线程按顺序执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-02
    • 2021-01-20
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    相关资源
    最近更新 更多