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

Can I make a thread-safe std::atomic<vector<int>>?

本文关键字:gt lt atomic vector int std 安全 线程 一个 我可以      更新时间:2023-10-16

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

由于std::vector不是线程安全的,我考虑了std::mutex(这肯定会工作)。

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

c++ 11§29.5/1说

有一个泛型类模板原子。模板实参T的类型必须是可复制的(3.9)。

trivial copyable是什么意思?

§3.9告诉

标量类型、平凡可复制类类型(第9节)、此类类型的数组以及这些类型的cv限定版本(3.9.3节)统称为平凡可复制类型。

对于类类型(std::vector属于该类类型):

一个普通的可复制类是这样一个类:

  • 没有非平凡的复制构造函数
  • 没有非平凡移动构造函数
  • 没有非平凡的拷贝赋值操作符
  • 没有非平凡移动赋值操作符
  • 有一个简单的析构函数

根据这个列表,std::vector不是一般的可复制的,所以你不能使用std::atomic<std::vector<int>>

由于事先知道vector的大小,并且不需要使用需要将vector重新分配到不同位置的方法(如push_back))。您可以使用std::vector<int>::resize或size构造函数来预分配和预构造所需的int s。因此,你的并发线程不需要操作vector本身,而需要操作vector的元素。

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

同样适用于int k[1000],它是微不足道的可复制的。但是你不需要这样做,因为线程不会改变数组/向量/列表本身,而是元素。

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

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

所以只要确保,你创建一个大小为n=1000的矢量,并根据你的线程号(1到4),你分配元素0-249,250-499等到你的线程。

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

Atomic可以用平凡的可复制类型实例化。Vector不是这样的类型