2

我有一个在线程 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);
}
4

1 回答 1

2

首先,如果您实际上没有尝试过使用默认(顺序一致)原子,测量您的应用程序的性能,对其进行分析,并显示观察到它们导致性能问题,我建议现在返回。

然而,如果你真的需要开始推理松弛原子......


尽管几乎可以肯定它可以在 x86 上运行,但这并不能保证达到您的预期。

我猜你正在使用它来保护其他一些非原子数据的发布。

在这种情况下,您需要保证如果您在读取器线程中读取了一个非零值,那么您在编写器中创建的非原子内存位置(即初始化您正在发布的数据)的各种其他副作用存储之前的线程将对读者线程可见。

读取非零std::memory_order_relaxed不与存储同步std::memory_order_release,因此您上面的代码没有此保证。

要获得我所描述的行为,您需要使用std::memory_order_acquire. 如果您使用的是 x86,那么获取不会产生任何内存围栏指令,因此它在性能上的唯一区别memory_order_relaxed是通过阻止一些编译器优化。

于 2012-11-21T00:44:15.690 回答