2

假设我有以下代码(玩具示例):

std::atomic<K *> data;
K *old_value = NULL;
K *new_value = new K();
if (!data.compare_exchange_strong(old_value, new_value, m1, m2)) {
    delete new_value;
}
do_something(old_value);

或者

std::atomic<K *> data;
K *i = data.load(m3);
K *j;
do {
   j = i + 1;
} while (data.compare_exchange_weak(i, j, m4, m5);
do_something(j);

m1m2m3m4的有效值是什么m5?我的解读是,所有代码都可以std::memory_order_relaxed作为整个代码强烈依赖于先前操作的结果(假设do_something只使用指针而不改变全局共享状态)。我的阅读正确吗?

4

1 回答 1

4

这个问题仅在具有明确定义的共享状态的多线程场景中才有意义。在不知道其他线程做什么的情况下,我只能假设它读取/写入data。仅通过这个单点同步,完全放松的排序就可以了。对于独立于其他同步点考虑的任何给定原子,操作仍然是原子的,并且它们的相对顺序仍然是正确的。

现在,如果共享状态由几个变量组成(这就是“排序”发挥作用的地方),那将是一个完全不同的故事;你将不得不担心获取/释放/等。语义。在这种情况下:

relaxed

  • 不保证从一个线程对多个变量的更改将以相同的顺序对另一个线程可见;
  • 不保证对独立于不同线程(例如线程 1 组data1和线程 2 组data2)的多个变量的更改将以相同的顺序对所有其他线程可见。

acquire/release(分别用于每次读/写时;对于不同的排序参数模式,第一项可能会变得更轻松)

  • 保证从一个线程对多个变量的更改将以相同的顺序对另一个线程可见;
  • 不保证对独立于不同线程的多个变量的更改将以相同的顺序对所有其他线程可见。

seq_cst(再次,在每次读/写时使用):

  • 保证从一个线程对多个变量的更改将以相同的顺序对另一个线程可见;
  • 保证对独立于不同线程的多个变量的更改将以相同的顺序对所有其他线程可见,无论它可能是什么。
于 2012-08-01T17:29:25.197 回答