我可以创建一个线程安全的std :: atomic <vector <int>&gt;?

时间:2015-09-21 11:30:29

标签: c++ multithreading c++11 vector

我有一个需要执行n=1000次的功能。此函数执行蒙特卡洛样式模拟,并返回int作为结果。我想并行运行nthreads=4。每当一个线程完成一个循环时,它应该将结果放在std::vector<int>中。 因此,在1000个周期之后,我有一个1000 int的向量,可以通过统计检查。

由于std::vector不是线程安全的,我考虑过std::mutex(肯定会有效)。

但是我想知道我是否可以将一个向量声明为原子并因此绕过互斥体? 是否可以拥有std::atomic<std::vector<int>>?我可以使用push_back等吗?

3 个答案:

答案 0 :(得分:22)

C ++11§29.5/ 1说

  

有一个泛型类模板atomic。模板参数T的类型应该是可以轻易复制的(3.9)。

简单易懂的是什么意思?

§3.9告诉

  

标量类型,简单的可复制类类型(第9节),此类型的数组以及这些类型的cv限定版本(3.9.3)统称为普通可复制类型。

对于类类型(std::vector是):

  

一个简单的可复制类是一个类:

     
      
  • 没有非平凡的副本构造函数
  •   
  • 没有非平凡的移动构造函数
  •   
  • 没有非平凡的副本分配运算符
  •   
  • 没有非平凡的移动分配操作符
  •   
  • 有一个简单的析构函数
  •   

根据此列表std::vector并非易于复制,因此您无法使用std::atomic<std::vector<int>>

由于您事先知道了大小,因为您不需要使用需要在不同位置重新分配向量的方法(例如push_back)。)您可以使用std::vector<int>::resize或大小构造函数预分配和预构建所需的int。因此,并发线程不需要对向量本身进行操作,而是对元素进行操作。

如果没有从不同线程访问同一元素,则没有竞争条件。

int k[1000]也是如此,这是可以轻易复制的。但是你不需要它,因为线程不会改变数组/向量/列表本身而是元素。

答案 1 :(得分:9)

你不需要。如果

,从多个线程访问ja std::vector是完全可以的
  • 你读过对象
  • 您写入不同的对象

因此,请确保您创建一个大小为n=1000的向量,并根据您的线程编号(1到4)为您的线程分配元素0-249,250-499等。

因此,每个线程都会计算n/nthreads个元素。

答案 2 :(得分:4)

Atomic可以使用简单的可复制类型进行实例化。矢量不是这种类型。