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

+4

'erase'使迭代器无效,'remove_if'指定所有地方的元素......为什么地球上你会认为这可能是安全的? –

+0

我对C++ 11 STL相当陌生....其他高级语言(例如Python的列表)具有让您摆脱这种事情的数据结构。是否有任何*不同的* STL容器,这将*安全? –

+0

btw ...我知道我可以用std :: mutex做这个,只是防止任何*完全并发访问vector,但是我所能做的是能够在/从list中插入/删除东西“*无*使整个收藏无效。std :: list fair有没有更好的方法,还是它真的在T2中修改容器使T1中的迭代器无效? –

没有!如果另一个线程添加或删除项目中的元素,则thread1中的迭代器将变为无效。

这与items.remove类似,返回一个新的有效迭代器,因此您可以在从集合中删除元素时继续迭代。

+0

它提供了一个非常好的答案!我可能会以不同的方式说出来。行为完全未定义 – pm100