簡體   English   中英

如何在std :: deque中避免`deque iterator not dereferencable`? 鎖?

[英]How to avoid `deque iterator not dereferencable` in a std::deque ? Locks?

目前在我的項目中我有兩個靜態方法PushObjectsProcessObject PushObject方法將數據推送到靜態雙端隊列,這個方法可以被多個線程訪問,但ProcessObject總是由一個線程使用,用於從頂部檢索對象並刪除它們。現在我的問題是無論我是什么嘗試我總是最終(遲早會得到一個deque iterator not dereferencable error.Any建議我可以做什么來阻止這個問題。我的PushObjectsProcessObject的摘要在下面給出

    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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM