为了账号安全,请及时绑定邮箱和手机立即绑定

是否会在其他线程中始终以相同的顺序看到对不同线程中不同位置的两次原子写操作?

/ 猿问

是否会在其他线程中始终以相同的顺序看到对不同线程中不同位置的两次原子写操作?

C++
繁星点点滴滴 2020-02-02 14:43:35

与我之前的问题类似,请考虑以下代码


-- Initially --

std::atomic<int> x{0};

std::atomic<int> y{0};


-- Thread 1 --

x.store(1, std::memory_order_release);


-- Thread 2 --

y.store(2, std::memory_order_release);


-- Thread 3 --

int r1 = x.load(std::memory_order_acquire);   // x first

int r2 = y.load(std::memory_order_acquire);


-- Thread 4 --

int r3 = y.load(std::memory_order_acquire);   // y first

int r4 = x.load(std::memory_order_acquire);

是怪异的结果 r1==1, r2==0,并r3==2, r4==0有可能在C ++ 11内存模型下,这种情况下?如果我要全部替换std::memory_order_acq_rel成该std::memory_order_relaxed怎么办?


在x86上,这样的结果似乎是被禁止的,请参见此SO问题,但我一般是在询问C ++ 11内存模型。


奖励问题:


我们都同意,与std::memory_order_seq_cst该怪异的结果不会在C ++ 11被允许。现在,赫伯·萨特(Herb Sutter)在他著名的- atomic<>武器谈话 @ 42:30中说std::memory_order_seq_cst,这就像- std::memory_order_acq_rel 但 std::memory_order_acquire -loads可能不会在std::memory_order_release-writes 之前移动。我看不到上面示例中的此附加约束如何防止出现奇怪的结果。谁能解释?


查看完整描述

3 回答

?
蓝山帝景

问题中的更新的1代码( 在线程4中进行了装载x和y交换)实际上测试了所有线程是否同意全局存储顺序。


在C ++ 11内存模型下,结果r1==1, r2==0, r3==2, r4==0是允许的,实际上在POWER上是可观察的。


在x86上,这种结果是不可能的,因为在那里“其他处理器以一致的顺序看到存储”。在顺序一致执行中也不允许此结果。


注:1:这个问题原本有两个读者阅读x,然后y。甲顺序一致的执行是:


-- Initially --

std::atomic<int> x{0};

std::atomic<int> y{0};


-- Thread 4 --

int r3 = x.load(std::memory_order_acquire);


-- Thread 1 --

x.store(1, std::memory_order_release);


-- Thread 3 --

int r1 = x.load(std::memory_order_acquire);

int r2 = y.load(std::memory_order_acquire);


-- Thread 2 --

y.store(2, std::memory_order_release);


-- Thread 4 --

int r4 = y.load(std::memory_order_acquire);

结果是r1==1, r2==0, r3==0, r4==2。因此,这根本不是一个奇怪的结果。


为了说每个读者看到的商店顺序不同,我们需要他们以相反的顺序阅读,以排除最后一个商店只是被延迟了。


查看完整回答
反对 2020-02-02
?
慕的地6264312

是怪异的结果 r1==1, r2==0,并r3==0, r4==2有可能在C ++ 11内存模型下,这种情况下?


是。C ++内存模型允许这种奇怪的结果。


如果我要全部替换std::memory_order_acq_rel成该std::memory_order_relaxed怎么办?


如果更换所有memory_order_acquire和memory_order_release通过memory_order_relaxed,没有什么改变你的代码。


std::memory_order_seq_cst就像,std::memory_order_acq_rel但是std::memory_order_acquire-loads在std::memory_order_release-writes 之前可能不会移动。我看不到上面示例中的此附加约束如何防止出现奇怪的结果。


“ acquire-load可能不会在release-writes 之前移动。” 显示了顺序一致性约束(memory_order_seq_cst)的一方面。


在C ++内存模型中,它仅保证seq_cst具有acq_rel语义,并且所有 seq_cst原子访问不会多多少少都具有“总顺序”。当存在这样的“总顺序”时,我们无法得到怪异的结果,因为所有seq_cst原子访问都好像在单个线程上以任何交错顺序执行一样。


您先前的问题对待单个原子变量的“一致性” ,而这个问题要求所有原子变量的“一致性” 。C ++内存模型可确保单个原子变量甚至最弱的排序()的直观一致性relaxed,以及不同原子变量的“顺序一致性”,只要默认排序(seq_cst)。seq_cst如您所指出的那样,当您使用显式无序原子访问时,这可能是奇怪的结果。


查看完整回答
反对 2020-02-02

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信