以下代码是否是更新原子变量最大值的正确实现? 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解决了基本相同的问题(尽管在特定的上下文中),但(接受的)答案并不是决定性的,特别是关于内存顺序(并且可能已过时)。
答案 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
,编译器仍然可以自由地应用编译时重新排序