![](/img/trans.png)
[英]'deque iterator not dereferencable` while doing std::deque->front()
[英]How to avoid `deque iterator not dereferencable` in a std::deque ? Locks?
目前在我的項目中我有兩個靜態方法PushObjects
和ProcessObject
。 PushObject
方法將數據推送到靜態雙端隊列,這個方法可以被多個線程訪問,但ProcessObject
總是由一個線程使用,用於從頂部檢索對象並刪除它們。現在我的問題是無論我是什么嘗試我總是最終(遲早會得到一個deque iterator not dereferencable
error.Any建議我可以做什么來阻止這個問題。我的PushObjects
和ProcessObject
的摘要在下面給出
void foo::PushObjects(obj A)
{
try
{
{//Begin Lock
boost::lock_guard<boost::mutex> lock(mutex_push);
mydeque.push_back(A);
}//End Lock
condition_read.notify_one(); //Inform the reader that it could start reading
}
catch (std::exception& e)
{
__debugbreak();
}
}
This is the static Reader method
void foo::ProcessObject()
{
{//Begin Lock
boost::unique_lock<boost::mutex> lock(mutex_process);
while(true)
{
while(mydeque.empty()) { condition_read.wait(lock); }
try
{
if(!mydeque.empty())
{
obj a = mydeque.front();
......Process the object........
mydeque.pop_front();
}
}
catch (std::exception& e)
{
__debugbreak();
}
}//end while
}//End lock
}
從我所讀到的是,一旦在雙端隊列中添加或刪除項目,迭代器就會變為無效。 有沒有辦法解決這個問題。
看起來你沒有使用相同的互斥鎖( 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();
您可能不需要鎖定(或至少不需要相同的鎖)來處理對象。 通過這種方式,您的編寫者仍然可以在處理時寫入雙端隊列。 另外需要注意的是,沒有什么可以阻止你成為多生產者多消費者,而不僅僅是多生產者單一消費者。
在您處理項目時,盡快擴展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項目,您最終獲得鎖定/獲取所有項目/解鎖/處理所有項目 ,因為鎖定互斥鎖是一個很大的性能影響,因此效率更高。
顯然, 這僅適用於單一消費者模式 。 如果您有多個消費者,您實際上不希望將單個消費者中的所有項目排入隊列,並讓所有其他消費者閑置。
您需要使用單個互斥鎖來訪問mydeque
沒有讀/寫互斥鎖。 任何對雙端隊列的訪問都必須在互斥鎖定時進行。 即使你只是檢查空()。 由於deque操作不是原子操作,因此最終mydeque.empty()
返回false,而在push_back中間處於某種半空狀態。 因此你需要boost::lock_guard<boost::mutex> lock(mutex_push);
在每次訪問mydeque之前。 或在整個操作過程中改變雙端內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.