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

dan*_*ani 18 c++ multithreading vector c++11

我有一个需要执行的功能n=1000.此函数执行蒙特卡罗样式模拟并返回int结果.我想nthreads=4和平奔跑.每当一个线程完成一个循环时,它应该将结果放入a std::vector<int>.因此,在1000个循环后,我有一个1000 ints 的向量,可以通过统计检查.

由于a std::vector不是线程安全的,我想std::mutex(这肯定会起作用).

但我想知道我是否可以声明一个矢量是原子的,从而绕过互斥体?有没有可能std::atomic<std::vector<int>>?我可以使用push_back等吗?

Pix*_*ist 23

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或者使用size构造函数来预分配和预构建所需的ints.因此你的并发线程会做不需要对向量本身进行操作,而是对元素进行操作.

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

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


Uni*_*rsE 10

你不需要.如果,std::vector从多个线程访问ja是完全可以的

  • 你读对象
  • 你写不同的对象

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

所以你的每个线程都会计算n/nthreads元素.

  • 在将向量的一部分分配给线程之前,向量的大小是非常重要的 - 任何大小调整绝对不是线程安全的. (9认同)
  • 但是即使你这样做,你仍然需要在读者和作者之间进行同步。特别是,但不仅如此,因为除非您使用 `atomic_int` 或 `std::atomic&lt;int&gt;`,否则不能保证对 `int` 的访问在所有架构上都是原子的。 (2认同)

Daw*_*dPi 5

原子可以用普通的可复制类型实例化。向量不是这种类型。