以原子方式更新最大值

时间:2017-06-28 10:55:14

标签: c++ multithreading max atomic

以下代码是否是更新原子变量最大值的正确实现? std::memory_order_relaxed对成功和失败的使用是否正确且最佳?

template<typename T>
inline void update_max(std::atomic<T> & atom, const T val)
{
  for(T atom_val=atom;
      atom_val < val &&
      !atom.compare_exchange_weak(atom_val, val, std::memory_order_relaxed);
     );
}

请注意,this question解决了基本相同的问题(尽管在特定的上下文中),但(接受的)答案并不是决定性的,特别是关于内存顺序(并且可能已过时)。

1 个答案:

答案 0 :(得分:2)

用于以线程安全方式自动更新最大值的策略是正确的。

由于您没有显示的代码,无法判断内存排序是否正确。 如果原子最大值不是在报告值之外的任何上下文中使用(即不依赖于其他内存操作),那么您可能会使用std::memory_order_relaxed

正如我在评论中提到的,在X86上,无论使用内存排序参数,编译器都可能生成相同的汇编指令。 X86是一个强有序的CPU,这意味着(默认情况下)#LoadLoad#LoadStore不允许重新排序。因此,您无法找到一个(理智的)编译器,它会在seq_cst load周围发出内存栅栏。 (默认情况下仍然允许#StoreLoad重新排序,但为了防止seq_cst排序通常在store方处理。

至于compare_exchange_weak(读 - 修改 - 写操作),这需要锁定高速缓存行才能成为原子;您将在X86上看到这些装配说明:lock cmpxchg
由于这也可以作为完整的记忆屏障,因此无需额外的围栏。

请注意,如果在任何原子操作上使用std::memory_order_relaxed,编译器仍然可以自由地应用编译时重新排序