我对 轻松订购
的说法感到困惑即使使用宽松的内存模型,也不允许出现凭空出现的值 循环依赖于它们自己的计算,例如 x y 最初为零,
// Thread 1: r1 = y.load(std::memory_order_relaxed); if (r1 == 42) x.store(r1, std::memory_order_relaxed); // Thread 2: r2 = x.load(std::memory_order_relaxed); if (r2 == 42) y.store(42, std::memory_order_relaxed);
不允许产生 r1 == r2 == 42 因为只有将 42 存储到 x 时才可能将 42 存储到 y 存储 42,循环依赖于 y 存储 42 的存储。 注意 在 C++14 之前,这在技术上是规范所允许的, 但不推荐实施者。
我用下面的代码做了测试,运行了大约2个小时,既没有出现r1 == 42,也没有出现r2 == 42。
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<int> x(0);
std::atomic<int> y(0);
int r1 = 0;
int r2 = 0;
void foo1() {
r1 = y.load(std::memory_order_relaxed);
if (r1 == 42) {
x.store(r1, std::memory_order_relaxed);
}
}
void foo2() {
r2 = x.load(std::memory_order_relaxed);
if (r2 == 42) {
y.store(42, std::memory_order_relaxed);
}
}
int main() {
while (1) {
std::thread t1(foo1);
std::thread t2(foo2);
t1.join();
t2.join();
if (r1 == 42 || r2 == 42) {
break;
}
}
std::cout << "r1 " << r1 << ", r2 " << r2 << std::endl;
return 0;
}
操作系统:Ubuntu 22.04.03 LTS (WSL2)
G++:11.4.0
编译命令:g++ -std=c++11 test.cpp -pthread
我的问题是: “请注意,在 C++14 之前,规范在技术上允许这样做,但不建议实现者这样做。”方法? 这是否意味着使用 C++11 可以使用此代码生成 r1 == r2 == 42 ?如果是这样,为什么这可能?
这是否意味着用 C++11 可以用此代码生成 r1 == r2 == 42 ?如果是这样,为什么这可能?
是的,技术上是允许的。这是可能的,因为这是允许的。任何硬件/实现是否真正能够产生该结果是一个与语言规范允许的不同的问题。