2

我正在查看 boost 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 如何冲突,我将不胜感激?

4

1 回答 1

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 接触同一个变量并且其中至少有一个变量写入它,那么就会出现竞争条件。

于 2013-11-03T03:36:17.600 回答