在我的程序中,我有一些线程正在运行。每个线程都获得指向某个对象的指针(在我的程序中 - 向量(。每个线程都会修改向量。
有时我的程序会因 segm 错误而失败。我认为这是因为线程 A 开始对向量执行某些操作,而线程 B 尚未完成对它的操作?难道是真的?
我应该如何解决它?线程同步?或者也许VectorIsInUse
做一个标志,并在使用它时将此标志设置为 true?
vector
与所有 STL 容器一样,不是线程安全的。您必须自己显式管理同步。可以使用std::mutex
或boost::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
。
这就是为什么几乎每个提供线程的类库也有同步原语,如互斥锁/锁。您需要设置其中之一,并获取/释放共享项目上每个操作的锁(读取和写入操作,因为您也需要防止在写入过程中发生读取,而不仅仅是防止同时发生多个写入(。