C++ 11和较新的STL的std ::向量和线程安全
假设我有一个包含shared_ptrs项向量:C++ 11和较新的STL的std ::向量和线程安全
std::vector<std::shared_ptr<Foo>> items;
它是安全的,通过该矢量的项目在一个线程中进行迭代:
thread1()
{
for(auto foo : items)
{
foo->something();
}
}
虽然另一个线程从该向量中删除项目?
thread2()
{
items.erase(std::remove_if(items.begin(), items.end(),
[](std::shared_ptr<Foo>& foo){
return foo->shouldBeRemoved();
}));
}
所以,换句话说:如果线程2,而线程1中删除的项目正在访问的话,会在矢量本身仍然有效/无腐败?
我很清楚,在这个例子中,我确定Foo :: something()和Foo :: shouldBeRemoved()不会引起任何问题,如果两个线程都在相同的ptr上时间。
而且我知道该向量是否直接包含Foo()的实例线程2可以在线程1尝试使用它时删除某些内容。在理论上使用shared_ptr应该防止被引用的对象在使用时被删除,所以它的迭代器/矢量的完整性是有问题的。
更新: 给其他人用类似的问题奋力精良的快速参考文档上这种事情,这似乎掩盖它为我的目的:
http://en.cppreference.com/w/cpp/container#Thread_safety
迭代器操作(例如增加一个迭代器)读取,但不要修改底层容器,并可能在同一容器上的其他迭代器上同时执行 操作,而使用const 成员函数或读取元素。 容器操作 使任何迭代器都无效修改容器,并且不能与 同时对现有迭代器执行任何操作,即使 (如果这些迭代器未失效)。
SO回答总结迭代器失效规则: Iterator invalidation rules
没有!如果另一个线程添加或删除项目中的元素,则thread1中的迭代器将变为无效。
这与items.remove类似,返回一个新的有效迭代器,因此您可以在从集合中删除元素时继续迭代。
它提供了一个非常好的答案!我可能会以不同的方式说出来。行为完全未定义 – pm100
'erase'使迭代器无效,'remove_if'指定所有地方的元素......为什么地球上你会认为这可能是安全的? –
我对C++ 11 STL相当陌生....其他高级语言(例如Python的列表)具有让您摆脱这种事情的数据结构。是否有任何*不同的* STL容器,这将*安全? –
btw ...我知道我可以用std :: mutex做这个,只是防止任何*完全并发访问vector,但是我所能做的是能够在/从list中插入/删除东西“*无*使整个收藏无效。std :: list fair有没有更好的方法,还是它真的在T2中修改容器使T1中的迭代器无效? –