是否在矢量C ++中读取和写入矢量线程安全操作?

时间:2019-03-15 14:50:22

标签: c++ multithreading vector thread-safety

我有下面的代码有时会导致分段错误?

vector<int> myvector;
void function1()
{
    for(int i = 0;i<10;i++)
    {
        cout<<"writer thread:"<<i<<endl;
        myvector.push_back(i);
    }
}
void function2()
{
    for(int i = 0;i<10;i++)
    {
        cout<<"reader thread:";
        cout<<myvector[i]<<endl;
    }
}
int main()
{

    thread t1(function1);
    thread t2(function2);

    t1.join();
    t2.join();
}

我对一般容器(尤其是向量)上的线程安全规则/保证不感到困惑。在一次采访中有人问我这个问题,但没有说出为什么在线程上写和在其他线程上写不是线程安全操作。

在以下用于向量的push_back的链接中的

,我在“数据争用”部分下看到“否则,将不访问任何现有元素,并且可以安全地同时访问或修改它们”。该语句如何证明矢量写入操作不是线程安全的?

http://www.cplusplus.com/reference/vector/vector/push_back/

4 个答案:

答案 0 :(得分:3)

那是不安全的。想象一下,您只是先运行第二个线程,然后再开始执行第一个线程(完成后)。您认为您的代码会做什么?

因此,即使std::vector对于并发访问是超级线程安全的(不是),代码仍然非常错误。

答案 1 :(得分:3)

来自有效STL的Scott Meyers,项目12:“对STL容器的线程安全抱有现实期望”。

  
      
  • 多个阅读器很安全。多个线程可以同时读取单个容器的内容,这将正常工作。自然,在读取过程中一定不能有任何写程序对容器起作用。

  •   
  • 将多个写入器放到不同的容器中是安全的。多个线程可以同时写入不同的容器。

  •   
     

仅此而已,让我明确地说,这是您可以希望,而不是您可以期望

我想我不必在这里提供任何其他解释:)

答案 2 :(得分:2)

否,std::vector<>的使用方式不是线程安全的。仅在以下情况下才是线程安全的:

  1. 所有线程仅从向量读取
  2. 如果一个线程写入向量,则不会同时进行读取操作。

function2的运行时间早于function1时,会发生分段错误。 ``例如,function1我将访问未推送到向量的myvector[4]。在这种情况下,您将获得“绑定外访问”错误,并且根据系统其余部分的工作情况,这可能导致读取错误的数据或分段错误。

答案 3 :(得分:2)

规则是:如果在线程之间访问了一个共享对象,并且这些线程中至少有一个是writer,则需要同步。没有它,您将发生数据争用,这是未定义的行为。

在您的情况下,由于您在写入向量时正在读取向量,因此它绝对不是线程安全的。

相关问题