C++ 写std::vector与普通数组的线程安全性
我读过没有一个STL容器是线程安全的。但这在实践中意味着什么?这是否意味着我应该将可写数据存储在普通数组中 我预计对std::vector::push_back(element)的并发调用可能会导致数据结构不一致,因为这可能需要调整向量的大小。但是,对于这样一个不涉及调整大小的情况呢:C++ 写std::vector与普通数组的线程安全性,c++,stl,thread-safety,openmp,C++,Stl,Thread Safety,Openmp,我读过没有一个STL容器是线程安全的。但这在实践中意味着什么?这是否意味着我应该将可写数据存储在普通数组中 我预计对std::vector::push_back(element)的并发调用可能会导致数据结构不一致,因为这可能需要调整向量的大小。但是,对于这样一个不涉及调整大小的情况呢: 使用数组: int数据[n]; //在此处初始化值。。。 #pragma-omp并行 对于(int i=0;i
int数据[n];
//在此处初始化值。。。
#pragma-omp并行
对于(int i=0;i
std::矢量数据;
数据。调整大小(n);
//在此处初始化值。。。
#pragma-omp并行
对于(int i=0;i
第一个实现真的比第二个实现更好吗a)在线程安全方面,b)在性能方面?我更喜欢使用std::vector,因为我不太习惯使用C风格的数组
< >编辑:我删除了一个<代码> >语法> OMP原子更新<代码>保护写.< /p> 它的主要意思是,如果你有多个线程访问向量,你不能依赖C++来阻止你用多个并发写来破坏数据结构。所以你需要使用某种防护装置。另一方面,如果您的程序没有使用多个线程,正如您的示例所示,那么您就完全可以了。在这种情况下,您应该只使用必要数量的值来构造向量?一切都会好起来的
std::vector<int> data(n, 0);
std::矢量数据(n,0);
resize()。表演将是平等的。
多线程访问不会损坏向量的原因是:您的数据位于它的位置,不会从那里移动。OMP线程一次不会访问同一个元素。两者同样安全。如果没有从多个线程访问元素,则可以。并行循环将只访问每个元素一次,因此只能从一个线程访问
在标准中,容器的成员函数是非线程安全的。在本例中,您使用了vector::operator[]
,因此您需要明确保证该成员的线程安全性,这似乎是合理的,因为即使在非常量向量上调用它也不会修改向量本身。因此,我怀疑在这种情况下是否存在问题,但我还没有寻找担保[编辑:rici发现了它]。即使它可能不安全,也可以在循环之前执行int*dataptr=&data.front()
,然后索引掉dataptr
,而不是data
顺便说一句,对于向量
,此代码不保证安全,因为它是一个对象中多个元素共存的特殊情况。对于bool
数组来说是安全的,因为其中的不同元素是不同的“内存位置”(C++11中的1.7)。对于指定数据竞争规则的C++11,描述了容器的线程安全性。本标准的相关章节为§23.2.2第2段:
尽管有(17.6.5.9)的规定,但当同时修改同一序列中不同元素(向量除外)中包含的对象的内容时,需要实现以避免数据竞争
[注:对于大小大于1的向量x,x[1]=5和*x.begin()=10可以在没有数据争用的情况下并发执行,但是x[0]=5和*x.begin()=10并发执行可能会导致数据争用。作为一般规则的例外,对于向量y,y[0]=true可以与y[1]=true争用。-结束说明]
上述§17.6.5.9基本上禁止任何标准库接口的任何并发修改,除非特别允许,因此第一节引用的内容准确地告诉您允许的内容(包括您的使用)
由于Steve Jessop提出了该问题,§23.2.2第1段明确允许在顺序容器中同时使用[]
:
为了避免数据竞争(17.5.9),实现应考虑以下功能:起始、结束、RRADE、RADE、前部、后部、数据、查找、下限、上限、均等范围、AT和除关联或无序的关联容器之外,运算符[]、
我没有足够的把握来回答这个问题,但我非常确定,对std::vector
的不同元素进行编写是线程安全的。这两个代码片段同样是线程安全的。“但这在实践中意味着什么?”:这意味着如果任何一个操作与并发写操作一致,则必须为写操作和读操作专门锁定容器。您可以让所有的读卡器敲打您想要的容器,但一旦引入了写电势,所有赌注都将关闭,您必须锁定所有访问权限(而不仅仅是其他写卡器)。一个单写多读锁可以很好地实现这一点,顺便说一句。升级到0。这可能被否决为不正确,但在删除的编辑之前发布:#pragma omp atomic update,它确实阻止并发写入,并在原始POST的上下文中使此答案正确。我编写了一个小测试函数,以查看openmp是否正常工作。我使用了vector
,将其大小调整为使用的线程数(初始化为false),并同时将所有值设置为true。如果每个值都为true,则函数返回true以显示所有线程都正确生成<代码>矢量
再次命中。幸运的是,我最近确实阅读了该标准的相关部分,因此我能够理解它,但是如果有人偶然发现了这一点,他们需要确保避免并发写入vector
,将_从每个对应的单独线程推回到std::vector
下的各个向量应该是安全的?