了解 C++ 中放松的内存顺序

Posted

技术标签:

【中文标题】了解 C++ 中放松的内存顺序【英文标题】:Understanding memory order relaxed in C++ 【发布时间】:2017-02-02 22:00:46 【问题描述】:
std::atomic<int> unique_ids;

void foo()     
  int i = unique_ids.fetch_add(1, std::memory_order_relaxed);
  std::cout<<i;


int main(int argc, char* argv[]) 
  std::vector<std::thread> threads;
  for (int i = 0; i < 9; ++i) 
       threads.emplace_back(foo);
  

  for (int i = 0; i < 9; ++i) 
      threads[i].join();
  
  std::cout << std::endl;
  return 0;

我的目标是使用 atomic 为并发程序生成唯一 id,但我不关心订单。

对于上面的代码,我的理解是 foo 中的输出值应该是不同的,虽然它们的顺序不能保证。

我对上面的代码进行了一百次测试,所有结果都符合我的预期。我是原子/内存顺序的初学者,谁能帮我澄清一下我的理解?

提前致谢。 爱民

附:我想指出,这个问题与c++,std::atomic, what is std::memory_order and how to use them 的问题不同,因为我的问题是专门关于对 memory_order_relaxed 的理解,而不是关于原子和内存顺序解释的一般性问题。

【问题讨论】:

@πάνταῥεῖ 这是关于memory_order_relaxed 而不是memory_order @πάνταῥεῖ 我认为我的问题与c++, std::atomic, what is std::memory_order and how to use them 的问题不同,因为我的问题专门关于对 memory_order_relaxed 的理解。谢谢。 @πάνταῥεῖ 这是关于一个特定问题,而不是一般概念。 dup 闭包不正确。 @πάνταῥεῖ 你真的不应该那样滥用你的黄金权力。通常的共识是关闭,而不是重新开放。重新打开是在极少数情况下使用的选项,通常用于修复不正确的关闭。 受骗者的信息是零散的,并且主要在 cmets 中,无法收到反对票,因为受骗者没有直截了当地提出这个问题。受骗者并没有真正回答这种特定类型的用例是否是放松内存排序的合法用途,这是这个问题明确提出的问题,IMO。 【参考方案1】:

这是对宽松内存排序的合法使用。您只需要相对于对同一原子的其他访问而言,该操作是原子的。无论内存顺序如何,每个原子操作都具有该特性,否则它根本就不是原子的。

【讨论】:

std::atomic unique_ids; for (int i=0; i @AiminHuang 假设unique_ids 从零开始。我不记得如果你不初始化它是否保证它被设置为零。 感谢您的澄清。我将在我的代码中初始化 unique_ids。 :)

以上是关于了解 C++ 中放松的内存顺序的主要内容,如果未能解决你的问题,请参考以下文章

大端字节顺序和小端字节顺序有啥区别

对c++内存顺序的理解,我错了吗?

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

并发编程-内存模型

C++题目时间限制: 1 Sec 内存限制: 128 MB

c++对象模型