C++ 从多个线程访问矢量

C++ Access to vector from multiple threads

本文关键字:访问 线程 C++      更新时间:2023-10-16

在我的程序中,我有一些线程正在运行。每个线程都获得指向某个对象的指针(在我的程序中 - 向量(。每个线程都会修改向量。

有时我的程序会因 segm 错误而失败。我认为这是因为线程 A 开始对向量执行某些操作,而线程 B 尚未完成对它的操作?难道是真的?

我应该如何解决它?线程同步?或者也许VectorIsInUse做一个标志,并在使用它时将此标志设置为 true?

vector 与所有 STL 容器一样,不是线程安全的。您必须自己显式管理同步。可以使用std::mutexboost::mutex来同步对vector的访问。

不要使用标志,因为这不是线程安全的:

  • 线程 A 检查isInUse标志的值,它是false
  • 线程 A 已挂起
  • 线程 B 检查isInUse标志的值,它是false
  • 线程 B 将isInUse设置为 true
  • 线程 B 挂起
  • 线程 A 已恢复
  • 线程 A 仍然认为isInUse false并将其设置为true
  • 线程 A 和线程 B 现在都可以访问vector

请注意,每个线程都必须在需要使用vector的整个时间内锁定它。这包括修改vector和使用vector的迭代器,因为如果迭代器引用的元素erase()vector进行内部重新分配,则迭代器可能会失效。例如,不要

mtx.lock();
std::vector<std::string>::iterator i = the_vector.begin();
mtx.unlock();
// 'i' can become invalid if the `vector` is modified.

如果你想要一个可以从多个线程安全使用的容器,你需要使用一个为此目的而显式设计的容器。标准容器的接口不是为并发突变或任何类型的并发而设计的,你不能只是锁定问题。

你需要像TBB或PPL这样的东西,里面有concurrent_vector

这就是为什么几乎每个提供线程的类库也有同步原语,如互斥锁/锁。您需要设置其中之一,并获取/释放共享项目上每个操作的锁(读取和写入操作,因为您也需要防止在写入过程中发生读取,而不仅仅是防止同时发生多个写入(。