2013-04-24 85 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