让x
和y
是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
答案 0 :(得分:1)
#StoreLoad
的重新排序可能会导致两个加载都返回旧值,因此您需要在所有4个操作上保持完全顺序一致性以防止出现这种情况。
读取存储缓冲区以了解是什么原因导致这种重新排序。
答案 1 :(得分:1)
您需要所有操作的顺序一致性。
发布/获取实际上并未在此处强加任何顺序,因为在发布存储之前没有存储,而在获取加载之后没有加载(这将由它进行排序)。
任意存储区上的内存排序放松,例如x.store
可能导致商店在两个线程中以不同顺序显示。然后,它不会违反其余操作的顺序排序,以使宽松的存储在另一个线程中加载后可见,而另一个存储在其相应的加载之后仍以顺序一致的总顺序进行排序。
通过对所有操作进行顺序排序,可以确保输出,因为必须在所有线程中以相同的方式观察到顺序操作的总顺序。此顺序必须与线程中的顺序顺序一致,即x.store < y.load
和y.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
因此获取或释放语义都不会产生任何差异。