2013-04-24 36 views
27

在串行代码,更新最大可以简单地通过如何自动更新最大值?

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

但是完成的,如何把这个为atomic<T>变量保存最大值来完成:

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(比较==而不是>)来执行此操作?怎么样?

请注意,显式锁定是不允许的(唯一允许的锁定是可能与执行std::atomic<T>一起执行的锁定)。

回答

30

它似乎并不在一个单一的操作是可能的,但你可以做一个循环,试图做到这一点,直到最后成功或原子变量值变为大于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)) 
     ; 
} 
+0

这是保证线程安全吗? – Walter 2013-04-24 11:32:14

+1

@zch:你不应该更新循环内的'prev_value'吗?否则,如果第一个'compare_exchange_weak'失败,它将始终与_potentially_“old”值进行比较,并且可能永远不会离开该循环。我对吗? – 2013-04-24 11:45:17

+1

@沃尔特,我想是的,但我没有强调测试它。 @AndréNeves,'compare_exchange_weak'在失败时进行更新 - 这就是为什么第一个参数是通过非const引用的原因。 – zch 2013-04-24 11:50:30