【问题标题】:How to atomically update a maximum value?如何以原子方式更新最大值?
【发布时间】:2013-04-17 21:23:26
【问题描述】:

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

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

但是,对于保持最大值的atomic&lt;T&gt; 变量,应该如何做到这一点:

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

显然,串行版本的代码不起作用,因为另一个线程可能会在加载和存储之间更改maximum_value。可以使用compare_exchange(比较== 而不是&gt;)来实现这一点吗?怎么样?

请注意,不允许使用显式锁(唯一允许的锁是std::atomic&lt;T&gt; 的实现可能附带的锁)。

【问题讨论】:

    标签: c++ c++11 concurrency atomic max


    【解决方案1】:

    在单个操作中似乎不可能,但您可以创建一个循环,尝试执行此操作,直到它最终成功或原子变量中的值变得大于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))
            {}
    }
    

    【讨论】:

    • @zch: 你不应该在循环内更新prev_value 吗?否则,如果第一个 compare_exchange_weak 失败,它将始终与 可能“旧”值进行比较,并且可能永远不会离开循环。我说的对吗?
    • @Walter,我认为是,但我没有对其进行压力测试。 @André Neves,compare_exchange_weak 在失败时进行更新 - 这就是为什么第一个参数是非常量引用的原因。
    • 关于 C++11 中 CAS 循环的文章:herbsutter.com/2012/08/31/…
    • @AndréNeves - compare_exchange_weak 更新 prev_value 如果比较失败。
    • @zch,PeteBecker:你们都是对的。谢谢指正!
    猜你喜欢
    • 2014-12-06
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多