使用 C++ 原子库,我应该使用啥内存顺序进行加载,然后进行比较交换?

Posted

技术标签:

【中文标题】使用 C++ 原子库,我应该使用啥内存顺序进行加载,然后进行比较交换?【英文标题】:Using the C++ atomic lib, what memory order(s) should I use for a load followed by a compare exchange?使用 C++ 原子库,我应该使用什么内存顺序进行加载,然后进行比较交换? 【发布时间】:2017-01-31 17:53:26 【问题描述】:

例如,多个线程执行 update() 函数:

// Statically allocated
atomic<int> high_water0;
//...
void update(int meas)

int i;
bool replaced;
do

i = high_water.load(?);
if (i >= meas)
  break;
replaced = high_water.compare_exchange_strong(i, meas, ?, ?);

while (!replaced);
// ...

(我正在尝试实现在多个线程中进行的单个测量的共享高水位标记。)

【问题讨论】:

【参考方案1】:

compare_exchange_strong 相对于high_water 是原子的,无论您指定什么内存顺序。内存排序仅与 other 内存操作有关。这在很大程度上取决于其他线程需要查看high_water 的方式和时间。由于meas 仅在此线程中可见,因此无需考虑其他加载和存储。因此,memory_order_relaxed 是正确的。


作为辅助说明,compare_exchange_strong 将第一个参数替换为观察值,因此执行 load 是多余的。

int i = high_water.load(std::memory_order_relaxed);
while (i < meas
      && high_water.compare_exchange_strong(i,
                                            meas,
                                            std::memory_order_relaxed,
                                            std::memory_order_relaxed
                                           )
      )
    continue;

【讨论】:

while ( i &lt; meas &amp;&amp; ! high_water.compare_exchange_strong(…) ) ;【参考方案2】:

我应该使用什么内存顺序进行加载,然后进行比较交换?

无法判断,因为您没有显示调用 update() 的代码。 如果您使用memory_order_relaxed(或任何比默认值更弱的东西),那么在某些平台上,围绕该调用的内存操作的重新排序是真实存在的。 high_water实际上可能用于在线程之间同步数据。 如果您不担心这些可能的重新排序,那么std::memory_order_relaxed 很好。

一般来说,对于这些类型的操作,我不会使用比默认 (std::memory_order_seq_cst) 更弱的排序。 由于std::compare_exchange_strong 是一个读取-修改-写入 (RMW) 操作,根据定义,它是昂贵的,因为它在核心之间同步原子的值, 改变内存顺序不会有太大的优势。至少在 X86 上,使用您的代码,编译器将为 std::memory_order_seq_cststd::memory_order_relaxed 发出完全相同的目标代码。

旁注,由于您处于循环中,您可能希望使用compare_exchange_weak(),这可能会虚假失败,但这是由循环处理的。

【讨论】:

以上是关于使用 C++ 原子库,我应该使用啥内存顺序进行加载,然后进行比较交换?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 标准库 - 我应该啥时候使用它,啥时候不应该使用它?

对于等待工作线程的主机线程,我应该使用哪种内存顺序?

C++ 原子内存顺序与诸如 notify() 之类的线程事件

C++ 库名称中的“f”后缀是啥意思,如何加载它?

你啥时候在 C++ 中对一个结构进行 ZeroMemory 处理?

在 C++ 中应该按啥顺序声明类? [关闭]