放宽顺序
标记为 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 中的断言似乎永远不会触发。
问题
但是,由于A 和B 之间没有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/