什么时候应该使用std :: atomic_compare_exchange_strong?

时间:2013-07-29 01:05:05

标签: c++ multithreading c++11 atomic compare-and-swap

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

根据cppreference

  

允许弱函数形式的虚假失败   即使它们是平等的,就好像* obj!= *一样。当一个   比较和交换处于循环中,弱版本将产生更好的效果   在某些平台上的表现。 当弱比较和交换时   需要一个循环,一个强大的不会,强大的循环   优选

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

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

有人可以举例说明比较和交换不在循环中,以便版本更好吗?

1 个答案:

答案 0 :(得分:9)

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用于提供互斥以确保某些线程执行清理任务。我们并不关心哪一个,但我们想确保一些线程可以访问(也许其他线程可以通过从current读取它的ID来观察获胜者。)

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

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])循环更有效的代码。