C ++ STL地图/矢量和线程安全矢量

时间:2011-01-18 14:42:53

标签: c++ boost stl thread-safety containers

我想知道下面的代码是否会被认为是线程安全的。我认为它应该是,但我不太熟悉引擎盖下发生的事情。

基本上,我在Foo类中有这个函数,它将在主线程上调用并将一个向量作为一个anrgument,即

void Foo::func( vector<int> v)

在Foo,我也有一个私人会员,

vector< vector<int> > vecOfVec;

func内,我只需将新的v推回到vecOfVec并检查v的大小。如果v小于预期的大小,我想启动另一个用{(1}}填充一些已知的预定值的线程,如此

v

void Foo::func( vector<int> v) { int size = v.size(); int index = vecOfVec.size(); vecOfVec.push_back(v); if (size < 1000) { boost::thread t( boost::bind( &Foo::PushBackZeros, this, vecOfVec, index) ); } } ,顾名思义就是用'零填充'vecOfVec [index]'的向量,直到它的大小增加到1000;

现在,我没有在Foo::PushBackZeros的任何元素上看到任何并发读取或写入操作。显然,有可能对整个对象进行并发操作,但永远不会有vecOfVec的特定元素的并发。

有人可以解释上述内容是否会被视为线程安全吗? STL地图也同样程度吗?如果没有,请解释。干杯!

3 个答案:

答案 0 :(得分:8)

我认为,这不是线程安全的。如果一个线程将一个新元素推送到向量上,导致向量的内部存储区域需要增长,会发生什么?推送线程可能会将内存更换为更大的缓冲区,这会导致与此操作并行读取的线程突然从无效(内存)内存中读取。或者线程在某些插槽中看到随机值,只是因为它们同时读取代码,该代码将向量内容从旧内存位置复制到新内存位置。

答案 1 :(得分:0)

如果您的Foo::PushBackZerosFoo::func( vector<int> v)具有相同的签名,那么它将是线程安全的,因为您将数组的副本传递给该函数。所以不会有并发访问。

答案 2 :(得分:0)

vecOfVec正在按值传递,因为boost :: bind要求你在引用参数周围放置一个boost :: ref。

很可能是线程安全的,但没有做你认为的那样。

我不确定为什么你需要传递该参数,因为它已经在“this”中。

尽管你想做什么,但要回答原来的问题:

  • 如果可以调整vecOfVecs的大小,那么其任何成员都可能无效,因此它不是线程安全的。
  • 将成员推入其中一个内部向量不会使任何其他成员向量无效,因此只要它们都已存在,就可以同时填充不同的向量成员。
  • 如果您提前“保留”,那么您可以将更多成员推送到您的向量中,直到达到该容量并且它不会使现有成员无效。