我想知道下面的代码是否会被认为是线程安全的。我认为它应该是,但我不太熟悉引擎盖下发生的事情。
基本上,我在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地图也同样程度吗?如果没有,请解释。干杯!
答案 0 :(得分:8)
我认为,这不是线程安全的。如果一个线程将一个新元素推送到向量上,导致向量的内部存储区域需要增长,会发生什么?推送线程可能会将内存更换为更大的缓冲区,这会导致与此操作并行读取的线程突然从无效(内存)内存中读取。或者线程在某些插槽中看到随机值,只是因为它们同时读取代码,该代码将向量内容从旧内存位置复制到新内存位置。
答案 1 :(得分:0)
如果您的Foo::PushBackZeros
与Foo::func( vector<int> v)
具有相同的签名,那么它将是线程安全的,因为您将数组的副本传递给该函数。所以不会有并发访问。
答案 2 :(得分:0)
vecOfVec正在按值传递,因为boost :: bind要求你在引用参数周围放置一个boost :: ref。
很可能是线程安全的,但没有做你认为的那样。
我不确定为什么你需要传递该参数,因为它已经在“this”中。
尽管你想做什么,但要回答原来的问题: