9

C++11 中有两个原子 CAS 操作:atomic_compare_exchange_weakatomic_compare_exchange_strong.

根据cppreference

函数的弱形式被允许虚假地失败,也就是说,即使它们相等,也可以像 *obj != *expected 一样行事。当比较和交换处于循环中时,弱版本将在某些平台上产生更好的性能。当弱比较和交换需要循环而强循环不需要时,强循环更可取

以下是使用版本的示例,我认为:

do {
    expected = current.value();
    desired = f(expected);
} while (!current.atomic_compare_exchange_weak(expected, desired));

有人可以举一个比较和交换不在循环中以便版本更可取的例子吗?

4

1 回答 1

10

这些atomic_compare_exchange_XXX函数用观察到的值更新它们的“预期”参数,因此您的循环与以下内容相同:

expected = current;
do {
    desired = f(expected);
} while (!current.atomic_compare_exchange_weak(expected, desired));

如果期望值独立于期望值,则此循环变为:

desired = ...;
expected = current;
while (current.atomic_compare_exchange_weak(expected, desired))
  ;

让我们添加一些语义。假设有几个线程同时运行它。在每种情况下desired都是当前线程的非零 ID,current用于提供互斥以确保某些线程执行清理任务。我们并不真正关心哪一个,但我们想确保某个线程可以访问(并且也许其他线程可以通过读取它的 ID 来观察获胜者current)。

我们可以通过以下方式实现所需的语义:

expected = 0;
if (current.atomic_compare_exchange_strong(expected, this_thread)) {
  // I'm the winner
  do_some_cleanup_thing();
  current = 0;
} else {
  std::cout << expected << " is the winner\n";
}

这是一种atomic_compare_exchange_weak需要循环来实现与 相同的效果的情况atomic_compare_exchange_strong,因为可能会出现虚假故障:

expected = 0;
while(!current.atomic_compare_exchange_weak(expected, this_thread)
       && expected == 0))
  ;
if (expected == this_thread) {
  do_some_cleanup_thing();
  current = 0;
} else {
  std::cout << expected << " is the winner\n";
}

该标准建议在这种情况下,实现可以提供atomic_compare_exchange_strong比循环更有效的代码..._weak(§29.6.5/25 [atomics.types.operations.req])。

于 2013-07-29T01:47:41.743 回答