最低订购要求

时间:2019-12-30 13:10:29

标签: c++ multithreading atomic relaxed-atomics

xystd::atomic<int>类型的两个不同变量,并假定它们两个的当前值为1。什么是最宽松的订购要求集,以便以下代码生成一些输出? (即order1 ... order4应该使用什么?)

// Thread 1
x.store(0, order1);       // A
if(0 == y.load(order2))   // B
  std::cout << '1';       // C
// Thread 2
y.store(0, order3);       // E
if(0 == x.load(order4))   // F
  std::cout << '2';       // G

3 个答案:

答案 0 :(得分:1)

#StoreLoad的重新排序可能会导致两个加载都返回旧值,因此您需要在所有4个操作上保持完全顺序一致性以防止出现这种情况。

读取存储缓冲区以了解是什么原因导致这种重新排序。

答案 1 :(得分:1)

您需要所有操作的顺序一致性。

发布/获取实际上并未在此处强加任何顺序,因为在发布存储之前没有存储,而在获取加载之后没有加载(这将由它进行排序)。

任意存储区上的内存排序放松,例如x.store可能导致商店在两个线程中以不同顺序显示。然后,它不会违反其余操作的顺序排序,以使宽松的存储在另一个线程中加载后可见,而另一个存储在其相应的加载之后仍以顺序一致的总顺序进行排序。

通过对所有操作进行顺序排序,可以确保输出,因为必须在所有线程中以相同的方式观察到顺序操作的总顺序。此顺序必须与线程中的顺序顺序一致,即x.store < y.loady.store < x.load。唯一的可能性是:

x.store < y.load  < y.store < x.load
x.store < y.store < x.load  < y.load
x.store < y.store < y.load  < x.load

y.store < x.load  < x.store < y.load
y.store < x.store < y.load  < x.load
y.store < x.store < x.load  < y.load

所有这些变量都观察到存储后加载的变量之一,从而触发cout语句之一。

例如x.store不是memory_order_seq_cst,因此,尽管仍需要在线程1中的y.load之前对其进行排序,但它可能在线程2中的x.load之后才可见。

y.load < y.store < x.load仍将满足其他操作的顺序一致性,并且无论如何都无法满足x的修改顺序。

答案 2 :(得分:0)

两个简单的规则:

  • 作为并行处理开始(线程开始)之后的第一个动作,发布隔离区或操作没有任何要显示的内容(在其他线程中),因此“发布”没有任何内容,并且发布是无用的(一切都是先前可见,并且在同时启动的线程中同样可见);
  • 作为并行处理结束(线程结束)之前的最后一个动作,获取栅栏或操作没有任何要显示的(在该线程中),而在通用父线程中是不可见的

您在这里:

x.store(0, order1);       // A
if(0 == y.load(order2))   // B
  • 开始时的商店
  • 最后的负载

因此获取或释放语义都不会产生任何差异。