目前在我的项目中,我有两个静态方法PushObjects
和ProcessObject
。 PushObject
方法将数据推送回静态双端队列,多个线程可以访问此方法,但ProcessObject
始终由单个线程使用,用于从顶部检索对象并删除它们。现在我的问题是无论我尝试什么,我总是最终(迟早会得到deque iterator not dereferencable
错误。关于我可以做些什么来阻止这个问题的任何建议。我的PushObjects
和{{1的摘要下面给出了
ProcessObject
从我所读到的是,一旦在deque中添加或删除项目,迭代器就会变为无效。有没有办法解决这个问题。
答案 0 :(得分:5)
您似乎没有使用相同的互斥锁(mutex_push
vs mutex_process
)来读取/写入deque
。你需要。写入内存并在不同线程上同时读取内存是不安全的。
其他说明:
obj a = mydeque.front();
......Process the object........
mydeque.pop_front();
如果您管理锁定以获得最短的锁定时间,那么可能会好得多......
obj a = std::move(mydeque.front());
mydeque.pop_front();
lock.unlock();
// process the object
lock.lock();
您可能不需要锁定(或至少不需要相同的锁)来处理对象。通过这种方式,您的编写者仍然可以在处理时写入双端队列。另外需要注意的是,没有什么可以阻止你成为多生产者多消费者,而不仅仅是多生产者单一消费者。
答案 1 :(得分:4)
在您处理项目时,尽快扩展Dave关于解锁的答案以允许并发写入......
你的双端队列可能包含几个项目(例如,当你还在处理另一个项目时已被推送)。为了避免锁定每个项目,你可以将你的双端队列交换为空的本地项目,并处理来自该本地双端队列的项目。有些代码会更清晰:
while (true) {
std::deque<Obj> tmp_deque;
{
std::unique_lock<std::mutex> lock(mutex);
while (mydeque.empty())
condition.wait(lock);
mydeque.swap(tmp_deque);
}
while (!tmp_deque.empty()) {
Obj obj = std::move(tmp_deque.front());
tmp_deque.pop_front();
// process obj
}
}
通过这种方式,您可以使用锁定/获取所有项目/解锁/处理所有项目,而不是锁定/获取1项目/解锁/处理1项因为锁定互斥锁是一个很大的性能影响,因此效率更高。
显然,这仅适用于单一消费者模式。如果你有多个消费者,你真的不想让一个消费者中的所有商品入队,让所有其他消费者都闲着。
答案 2 :(得分:3)
您需要单个互斥锁才能访问mydeque
无读/写互斥锁。任何对双端队列的访问都必须在互斥锁定时进行。即使你只是检查空()。由于deque操作不是原子操作,因此最终可能会返回mydeque.empty()
返回false,而在push_back中间处于某种半空状态。因此,在每次访问mydeque之前,您需要boost::lock_guard<boost::mutex> lock(mutex_push);
。或者在改变双端内容的整个操作过程中。