2013-04-24 48 views
27

Trong mã nối tiếp, cập nhật tối đa có thể được thực hiện đơn giản bằng cáchLàm cách nào để cập nhật nguyên tử giá trị tối đa?

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

Tuy nhiên, làm thế nào điều này sẽ được thực hiện cho một atomic<T> biến giữ giá trị lớn nhất:

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

Rõ ràng, mã từ phiên bản nối tiếp không hoạt động, vì một chuỗi khác có thể thay đổi maximum_value giữa tải và cửa hàng. Có thể sử dụng số compare_exchange (so sánh == thay vì >) để thực hiện việc này không? làm sao?

Lưu ý rằng khóa rõ ràng không được phép (khóa duy nhất được phép là có thể đi kèm với việc triển khai std::atomic<T>).

Trả lời

30

Nó dường như không thể trong một hoạt động đơn lẻ, nhưng bạn có thể làm cho một vòng lặp, mà cố gắng để làm điều này, cuối cùng cho đến khi nó thành công hay giá trị trong biến nguyên tử trở nên lớn hơn 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

chuỗi này có được đảm bảo an toàn không? – Walter

+1

@zch: bạn không nên cập nhật 'prev_value' bên trong vòng lặp? Nếu không, nếu 'compare_exchange_weak' đầu tiên thất bại, nó sẽ luôn luôn so sánh với một giá trị _potentially_ cũ và có thể không bao giờ rời khỏi vòng lặp. Tôi có đúng không? –

+1

@Walter, tôi nghĩ là vậy, nhưng tôi đã không kiểm tra nó. @ André Neves, 'compare_exchange_weak' hiện cập nhật khi nó không thành công - đó là lý do tại sao đối số đầu tiên là do tham chiếu không const. – zch

Các vấn đề liên quan