1

xy是两个不同类型的变量,std::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
4

3 回答 3

1

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

阅读存储缓冲区以了解导致这种类型重新排序的原因。

于 2019-12-30T14:05:52.407 回答
1

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

Release/acquire 实际上并没有在这里强加任何排序,因为在 release-store 之前没有 store 或者在 acquire-load 之后没有加载,这将由它排序。

任何存储上的宽松内存排序,例如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语句。

如果 eg x.storeis not memory_order_seq_cst,那么虽然它仍然需要y.load在线程 1 之前排序,但它可能在线程 2 之后变得可见x.load

y.load < y.store < x.load然后仍然会满足其他操作的顺序一致性,并且x无论如何都可以轻松满足的修改顺序。

于 2019-12-30T14:09:55.797 回答
-1

两个简单的规则:

  • 作为并行开始(线程开始)之后的第一个动作,释放栅栏或操作没有任何可见的东西(在其他线程中),所以没有任何东西“释放”并且释放是无用的(一切以前都是可见的并且同时启动的线程同样可见);
  • 作为并行性结束(线程结束)之前的最后一个操作,获取栅栏或操作没有任何东西可以使其可见(在该线程中),而这些内容在公共父线程中是不可见的

在这里你有:

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

所以无论是获取还是释放语义都不会产生任何影响。

于 2020-01-01T01:03:46.107 回答