我正在修改Atomic文档,我遇到了以下示例:
atomic<int> a(0);
thread1:
... /* A */
a.fetch_add(1, memory_order_release);
thread2:
int tmp = a.load(memory_order_acquire);
if (tmp == 1)
{
... /* B */
}
else
{
... /* C */
}
现在我对memory_order_release和memory_order_acquire仍感到有点困惑。文档将它们描述为:
memory_order_release
执行释放操作。非正式地说,阻止所有前面的 记忆操作要经过这一点重新排序。
memory_order_acquire
执行获取操作。非正式地说,阻止成功 在此之前要重新排序的内存操作。
即使有这些例子,我仍然有点困惑。如果有人能够解释上述定义的含义以及A和C如何发生冲突,我将不胜感激?
答案 0 :(得分:2)
这些定义意味着在存储到a
(问题中发布的定义)之后,A中的任何内存操作都不能重新排序。并且B或C中的任何操作都不能在另一个线程中a
的加载之前(问题中获取的定义)。
现在,该示例假设没有其他代码在a
上运行,或者至少写入a
。如果执行B,则意味着a
在加载tmp
时发生的值为1。要使a
具有值1,必须在fetch_add
与fetch_add
同步之前执行load
,这意味着A中的代码已完成执行。如果命中该特定代码路径,则操作的顺序为:
A
a.fetch_add(1,memory_order_release);
int tmp = a.load(memory_order_acquire);
B
现在其他选项是当load
发生时,值仍为0.这意味着第一个线程没有执行fetch_add
,但不能保证它在哪里可能正在执行。当线程2执行C时,A可能仍在执行(或者它甚至可能尚未启动,或者它可能已经完成)。
如果A和B都访问同一个变量,则没有冲突,因为原子保证B只能在A完成后才能执行。另一方面,C没有给出保证,所以如果A和C触摸相同的变量并且至少有一个变量写入,那么就存在竞争条件。