原子更新最大值
updating maximum value atomically
以下代码是否是更新原子变量最大值的正确实现?使用 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 基本上解决了相同的问题(尽管在特定上下文中),但(已接受的)答案不是决定性的,特别是关于内存顺序,(并且可能已过时)。
用于以线程安全方式自动更新最大值的策略是正确的。
由于您没有显示代码,因此无法判断内存排序是否正确。
如果除了报告一个值(即不依赖于其他内存操作)之外,没有在任何上下文中使用原子最大值,您可能会逃脱 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
,编译器仍然可以自由应用编译时重新排序
以下代码是否是更新原子变量最大值的正确实现?使用 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 基本上解决了相同的问题(尽管在特定上下文中),但(已接受的)答案不是决定性的,特别是关于内存顺序,(并且可能已过时)。
用于以线程安全方式自动更新最大值的策略是正确的。
由于您没有显示代码,因此无法判断内存排序是否正确。
如果除了报告一个值(即不依赖于其他内存操作)之外,没有在任何上下文中使用原子最大值,您可能会逃脱 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
,编译器仍然可以自由应用编译时重新排序