C ++内存模型:seq_cst加载是否与seq_cst存储同步? [英] C++ memory model: do seq_cst loads synchronize with seq_cst stores?

查看:154
本文介绍了C ++内存模型:seq_cst加载是否与seq_cst存储同步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++内存模型中,所有加载和所有顺序一致的操作的存储都具有总顺序.我想知道这如何与具有其他内存顺序的操作(在顺序一致的加载之前/之后进行排序)交互.

In the C++ memory model, there is a total order on all loads and stores of all sequentially consistent operations. I'm wondering how this interacts with operations that have other memory orderings that are sequenced before/after sequentially consistent loads.

例如,考虑两个线程:

std::atomic<int> a(0);
std::atomic<int> b(0);
std::atomic<int> c(0);

//////////////
// Thread T1
//////////////

// Signal that we've started running.
a.store(1, std::memory_order_relaxed);

// If T2's store to b occurs before our load below in the total
// order on sequentially consistent operations, set flag c.
if (b.load(std::memory_order_seq_cst) == 1) {
  c.store(1, std::memory_order_relaxed)
}


//////////////
// Thread T2
//////////////

// Blindly write to b.
b.store(1, std::memory_order_seq_cst)

// Has T1 set c? If so, then we know our store to b occurred before T1's load
// in the total order on sequentially consistent operations.
if (c.load(1, std::memory_order_relaxed)) {
  // But is this guaranteed to be visible yet?
  assert(a.load(1, std::memory_order_relaxed) == 1);
}

是否保证T2中的断言不会触发?

Is it guaranteed that the assertion in T2 cannot fire?

我正在这里寻找标准的详细引用.特别是,我认为这需要证明从T1中的b 与商店中的同步到T2中的b的负载,以便确定发生到a线程间的存储在a加载之前,但据我所知,标准说memory_order_seq_cst存储与负载同步,但并非相反.

I'm looking for detailed citations of the standard here. In particular I think this this would require showing that the load from b in T1 synchronizes with the store to b in T2 in order to establish that the store to a inter-thread happens before the load from a, but as far as I can tell the standard says that memory_order_seq_cst stores synchronize with loads, but not the other way around.

推荐答案

seq_cst负载是否与seq_cst存储同步?

Do seq_cst loads synchronize with seq_cst stores?

如果满足所有必要要求,它们就会执行;在您的示例代码中,assert可以触发

They do if all necessary requirements are met; in your example code, the assert can fire

§29.3.3
所有memory_order_seq_cst操作上都应有一个总顺序S

§29.3.3
There shall be a single total order S on all memory_order_seq_cst operations

此总顺序适用于seq_cst操作本身.孤立地,store(seq_cst)具有发布语义,而load(seq_cst)具有获取语义.

This total order applies to the seq_cst operations themselves.. In isolation, a store(seq_cst) has release semantics, whereas a load(seq_cst) has acquire semantics.

第29.3.1-2节[atomics.order]
memory_order_release,memory_order_acq_rel和memory_order_seq_cst:
存储操作对受影响的内存位置执行释放操作.
.....
§29.3.1-4[atomics.order]
memory_order_acquire,memory_order_acq_rel和memory_order_seq_cst:
加载操作对受影响的内存位置执行获取操作.

§29.3.1-2 [atomics.order]
memory_order_release, memory_order_acq_rel, and memory_order_seq_cst:
a store operation performs a release operation on the affected memory location.
.....
§29.3.1-4 [atomics.order]
memory_order_acquire, memory_order_acq_rel, and memory_order_seq_cst:
a load operation performs an acquire operation on the affected memory location.

因此,按照获取/释放排序规则,相对于seq_cst操作,对具有非seq_cst排序的原子操作(或非原子操作)进行了排序:

Therefore, atomic operations with non-seq_cst ordering (or non-atomic operations) are ordered with respect to seq_cst operations per the acquire/release ordering rules:

  • store(seq_cst)操作不能使用在其之前已排序的任何内存操作(即,按程序顺序排在较早的位置)进行重新排序..
  • load(seq_cst)操作不能用其后顺序的任何内存操作重新排序.
  • a store(seq_cst) operation cannot be reordered with any memory operation that is sequenced before it (i.e. comes earlier in program order)..
  • a load(seq_cst) operation cannot be reordered with any memory operation that is sequenced after it.

在您的示例中,尽管在b.load(seq_cst)之后对T1中的c.store(relaxed)进行了排序(线程间)(load是获取操作), 相对于b.store(seq_cst)T2中的c.load(relaxed)是无序的(这是一个释放操作,但不会阻止重新排序).

In your example, although c.store(relaxed) in T1 is ordered (inter-thread) after b.load(seq_cst) (the load is an acquire operation), c.load(relaxed) in T2 is unordered with respect to b.store(seq_cst) (which is a release operation, but it does not prevent the reordering).

您也可以查看a上的操作.由于没有针对任何对象进行排序,因此a.load(relaxed)可以返回0,从而导致assert触发.

You can also look at the operations on a. Since those are not ordered with respect to anything, a.load(relaxed) can return 0, causing the assert to fire.

这篇关于C ++内存模型:seq_cst加载是否与seq_cst存储同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆