C++:原子递增计数器变量

问题描述 投票:0回答:1

如果我有两个

std::atomic<int>
计数器,
a
b
(都只做增量)。我想要做的是如果严格小于
a
,则增加
b
,并返回 a 的旧值。在存在多个线程都尝试此操作的情况下,我可以在不使用锁的情况下完成此操作吗?

比较然后递增序列需要锁定以确保

a
在比较和递增之间不会改变

c++ locking
1个回答
0
投票

由于

a
b
严格递增,您可以使用
compare_exchange
来完成此操作。这个想法是,将
a
b
的值加载到局部变量中,比较这些局部变量,如果有必要,当且仅当它仍然等于其旧值时,尝试将 local_a+1 交换到
a
中(这正是比较交换确实)。如果失败,则表明其他人已成功更新
a
,因此您重试,包括比较。

int inc()
{
  // Load b and an into locals.
  int aVal = a;
  int bVal = b;
  while(aVal < bVal)
  {
    if (a.compare_exchange_weak(aVal, aVal+1))
    {
      // Success! Return the original value of a.
      return aVal;
    }

    // Note that if a compare_exchange fails then `aVal` will already be updated with the new value of `a` so we only need to reload `b`
    bVal = b;
  }

  // a >= b so don't do anything
  return -1;
}

您可能可以收紧加载和比较/交换的内存顺序,但这是最简单的版本。

还要注意,虽然其中有一个循环,但循环是非常正常的(事实上,compare_exchange 的 weak 版本是必需的),因此不必担心 - 这是因为对于每次迭代循环的至少一个线程已成功执行工作,因此系统作为一个整体的前进总是会发生。

© www.soinside.com 2019 - 2024. All rights reserved.