如何自动更新最大值?

Wal*_*ter 36 c++ concurrency atomic max c++11

在串行代码中,更新最大值可以简单地通过

template<typename T>
void update_maximum(T& maximum_value, T const& value) noexcept
{
  if(value > maximum_value) maximum_value = value;
}
Run Code Online (Sandbox Code Playgroud)

但是,如何对atomic<T>保存最大值的变量执行此操作:

template<typename T>
void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
{
   // want a lock-free, thread-safe implementation
}
Run Code Online (Sandbox Code Playgroud)

显然,串行版本的代码不起作用,因为另一个线程可能maximum_value在加载和存储之间发生变化.可以使用compare_exchange(比较==而不是>)来实现这个吗?怎么样?

请注意,不允许显式锁定(允许的唯一锁定是执行时可能出现的锁定std::atomic<T>).

zch*_*zch 39

它似乎不可能在单个操作中,但你可以创建一个循环,试图这样做,直到它最终成功或原子变量中的值变得大于value:

template<typename T>
void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
{
    T prev_value = maximum_value;
    while(prev_value < value &&
            !maximum_value.compare_exchange_weak(prev_value, value))
        ;
}
Run Code Online (Sandbox Code Playgroud)

  • 关于C++ 11中CAS循环的文章:http://herbsutter.com/2012/08/31/reader-qa-how-to-write-a-cas-loop-using-stdatomics/ (6认同)
  • @zch:你不应该在循环内更新`prev_value`吗?否则,如果第一个 `compare_exchange_weak` 失败,它将始终与 _potentially_ “旧”值进行比较,并且可能永远不会离开循环。我对吗? (4认同)
  • @AndréNeves - 如果比较失败,`compare_exchange_weak`会更新`prev_value`. (3认同)
  • @Walter,我想是的,但我并没有对它进行压力测试.@AndréNeves,`compare_exchange_weak`在失败时进行更新 - 这就是为什么第一个参数是非const引用的原因. (2认同)