Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 写std::vector与普通数组的线程安全性_C++_Stl_Thread Safety_Openmp - Fatal编程技术网

C++ 写std::vector与普通数组的线程安全性

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

我读过没有一个STL容器是线程安全的。但这在实践中意味着什么?这是否意味着我应该将可写数据存储在普通数组中

我预计对std::vector::push_back(element)的并发调用可能会导致数据结构不一致,因为这可能需要调整向量的大小。但是,对于这样一个不涉及调整大小的情况呢:

  • 使用数组:
  • int数据[n];
    //在此处初始化值。。。
    #pragma-omp并行
    对于(int i=0;i
  • 使用'std::vector``:
  • 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
    下的各个向量应该是安全的?