是否可以在 C++11 中使用后续顺序一致加载对存储版本进行重新排序

Can a store-release be reordered with a subsequent sequential-consistent load in C++11?

本文关键字:版本 存储 新排序 排序 加载 C++11 顺序 是否      更新时间:2023-10-16

具有std::memory_order_release到某个位置的存储可以通过后续加载从另一个位置重新排序,并具有std::memory_order_acquire

但是,可以将std::memory_order_release到某个位置的商店重新排序,然后从另一个位置加载std::memory_order_seq_cst吗?

类似地,与变量std::memory_order_seq_cst的存储是否可以通过后续加载从另一个位置重新排序std::memory_order_acquire

请考虑以下示例:

std::atomic<int> x{0};
std::atomic<int> y{0};
void thread1() {
    x.store(std::memory_order_release, 1);
    int r1 = y.load(std::memory_order_seq_cst);
    std::cout << r1 << std::endl;
}
void thread2() {
    y.store(std::memory_order_seq_cst, 1);
    int r2 = x.load(std::memory_order_acquire);
    std::cout << r2 << std::endl;
}

众所周知(http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/),如果两个std::memory_order_seq_cst都被它们的释放/获取对应物替换,则输出可能是两倍"0"。

在这个例子中,顺序一致性是否买了什么东西,或者输出仍然可以是两倍"0"?

不,在这个例子中,顺序一致性不会购买任何东西,输出仍然可以是"0"的两倍。

std::memory_order_seq_cststd::memory_order_acquire/release 之间的唯一区别是std::memory_order_seq_cst存储可能不会随着后续std::memory_order_seq_cst加载到不同的变量/位置而重新排序,请参阅 Herb Sutter 的"原子<>武器"演讲。(当然,存储可能永远不会随着后续加载到同一变量而重新排序。

但是,一旦只有一个(更不用说两个)内存顺序被削弱(就像示例中两个线程的情况一样),StoreLoad 重新排序可能会发生。这意味着,在示例中,两个负载可以在各自的存储之前重新排序。

这意味着,如果一个程序将孤独的std::memory_order_seq_cst替换为std::memory_order_release(如果它带有商店)或std::memory_order_acquire(如果它带有负载),则只包含一个std::memory_order_seq_cst并且仅包含std::memory_order_release/acquire的程序仍然是相同的程序。