我有一个内存变量,它在线程 A 中更新并在其他线程中读取。读者只关心该值是否非零。我保证一旦该值增加,它就永远不会回到零。 如下优化有意义吗? 换句话说,在读者方面,一旦满足了我的条件,我就不需要“栅栏”了。
std::atomic<int> counter;
writer:
increment()
{
counter.store(counter+1, std:memory_order_release)
}
reader:
iszero()
{
if (counter.load(std::memory_order_relaxed) > 0) return false;
// memory fence only if condition not yet reached
return (counter.load(std::memory_order_acquire) == 0);
}
最佳答案
首先,如果您尚未实际尝试使用默认(顺序一致)原子,测量应用程序的性能,对其进行分析,并显示观察到它们导致性能问题,我建议现在返回。
但是,如果您确实需要开始推理宽松原子......
虽然它几乎肯定可以在 x86 上运行,但不能保证达到您的预期。
我猜您正在使用它来保护其他一些非原子数据的发布。
在这种情况下,您需要保证如果您在读取器线程中读取非零值,那么会对非原子内存产生各种其他副作用您在存储之前在编写器线程中创建的位置(即初始化您要发布的数据)将对读取器线程可见。
使用 std::memory_order_relaxed
读取非零值不会与 std::memory_order_release
存储同步,因此上面的代码不会有这个保证。
要获得我所描述的行为,您需要使用std::memory_order_acquire
。如果您使用的是 x86,则 acquire 不会生成任何内存栅栏指令,因此它在性能上与 memory_order_relaxed
不同的唯一方法是阻止某些编译器优化。
关于C++ 原子加载排序效率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13483150/