C ++ 11和更新的STL std :: vector和线程安全

时间:2016-01-22 00:24:00

标签: multithreading c++11

假设我有一个包含项目的shared_ptrs的向量:

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();
      }));
}

换句话说:如果thread2在访问它时删除了一个项目,那么 vector 本身是否仍然有效/无损?

我很清楚,在这个例子中,如果两个线程同时击中同一个ptr,由我来确定Foo :: something()和Foo :: shouldBeRemoved()不会导致任何问题

我知道如果向量直接包含Foo()的实例,则线程2在尝试使用它时可以删除某些内容。在理论上使用shared_ptr应该可以防止被引用的对象在使用时被删除,因此它是有问题的向量的迭代器/完整性。

更新 对于其他有类似问题努力在这类事情上做好快速参考文档的人,这似乎涵盖了我的目的:

http://en.cppreference.com/w/cpp/container#Thread_safety

  

迭代器操作(例如,递增迭代器)读取,但不是   修改底层容器,并可以与之同时执行   使用const在同一容器上的其他迭代器上的操作   成员函数,或从元素中读取。 集装箱业务   无效的任何迭代器都会修改容器而不能   与现有迭代器上的任何操作同时执行   如果这些迭代器没有失效。

SO回答总结迭代器失效规则: Iterator invalidation rules

1 个答案:

答案 0 :(得分:2)

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

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