我有下面的代码有时会导致分段错误?
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的链接中的,我在“数据争用”部分下看到“否则,将不访问任何现有元素,并且可以安全地同时访问或修改它们”。该语句如何证明矢量写入操作不是线程安全的?
答案 0 :(得分:3)
那是不安全的。想象一下,您只是先运行第二个线程,然后再开始执行第一个线程(完成后)。您认为您的代码会做什么?
因此,即使std::vector
对于并发访问是超级线程安全的(不是),代码仍然非常错误。
答案 1 :(得分:3)
来自有效STL的Scott Meyers,项目12:“对STL容器的线程安全抱有现实期望”。
多个阅读器很安全。多个线程可以同时读取单个容器的内容,这将正常工作。自然,在读取过程中一定不能有任何写程序对容器起作用。
将多个写入器放到不同的容器中是安全的。多个线程可以同时写入不同的容器。
仅此而已,让我明确地说,这是您可以希望,而不是您可以期望。
我想我不必在这里提供任何其他解释:)
答案 2 :(得分:2)
否,std::vector<>
的使用方式不是线程安全的。仅在以下情况下才是线程安全的:
当function2
的运行时间早于function1
时,会发生分段错误。 ``例如,function1我将访问未推送到向量的myvector[4]
。在这种情况下,您将获得“绑定外访问”错误,并且根据系统其余部分的工作情况,这可能导致读取错误的数据或分段错误。
答案 3 :(得分:2)
规则是:如果在线程之间访问了一个共享对象,并且这些线程中至少有一个是writer,则需要同步。没有它,您将发生数据争用,这是未定义的行为。
在您的情况下,由于您在写入向量时正在读取向量,因此它绝对不是线程安全的。