簡體   English   中英

為什么使用boost的並發Hasmap不起作用

[英]Why does this Concurrent Hasmap using boost not work

我有以下並發哈希圖:

template<typename Key, typename Value>
class ConcurrentMap
{

public:
    ConcurrentMap() {};
    bool has(Key k)
    {
        boost::shared_lock<boost::shared_mutex> lock(schemaAccess);
        return m.find(k) != m.end();
    }

    void set(Key k, Value v)
    {
        boost::shared_lock<boost::shared_mutex> lock(schemaAccess);

        // set k, v
        if(m.find(k) != m.end())
        {
            boost::upgrade_lock<boost::shared_mutex> valueLock(*valueAccess[k]);
            boost::upgrade_to_unique_lock<boost::shared_mutex> valueUniqueLock(valueLock);

            m.at(k) = v;
        }
        // insert k, v
        else
        {
            lock.unlock();
            boost::upgrade_lock<boost::shared_mutex> schemaLock(schemaAccess);
            boost::upgrade_to_unique_lock<boost::shared_mutex> schemaUniqueLock(schemaLock);

            boost::shared_ptr<boost::shared_mutex> mtx = boost::make_shared<boost::shared_mutex>();
            valueAccess.insert(std::pair<Key, boost::shared_ptr<boost::shared_mutex> >(k, mtx));
            m.insert(std::pair<Key,Value>(k,v));
        }
    }

    Value get(Key k)
    {
        boost::shared_lock<boost::shared_mutex> lock(schemaAccess);
        return m.at(k);
    }

    bool get(Key k, Value& v)
    {
        boost::shared_lock<boost::shared_mutex> lock(schemaAccess);
        if(m.find(k) != m.end()){
            v = m.at(k);
            return true;
        }
        return false;
    }


private:
    std::map<Key, Value> m;

    std::map<Key, boost::shared_ptr<boost::shared_mutex> > valueAccess;
    boost::shared_mutex schemaAccess;

    //http://stackoverflow.com/questions/36468270/how-to-use-a-boostmutex-as-the-mapped-type-in-stdmap/36469809?noredirect=1#comment60552035_36469809
};

以及以下用法:

ConcurrentMap<int, cv::Mat> mapper;

void worker1(){
    int counter = 0;
    while(1){
        boost::this_thread::sleep(boost::posix_time::milliseconds(5));
        cv::Mat img = cv::Mat(1920,1080, CV_64F);
        cout << "w1" << counter++ << endl;
        mapper.set(0,img);
    }
}

void worker2(){
    int counter = 0;
    while(1){
        boost::this_thread::sleep(boost::posix_time::milliseconds(5));
        cout << "w2" << counter++ << endl;
        cv::Mat img;
        if(!mapper.get(0, img)) continue ;
        cout << img.rows << endl;
        cout << "done" << endl;
    }
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "loading_area_concat");


    boost::thread worker1_;
    boost::thread worker2_;
    worker1_ = boost::thread(worker1);
    worker2_ = boost::thread(worker2);

    ros::spin();

    return 0;
}

*** Error in `/home/raaj/catkin_ac2/devel/lib/loading_area/loading_area_concat': free(): invalid pointer: 0x00007fb71c000078 ***

但是,我的代碼一直在第二個線程的“ get”部分崩潰。 如果我注釋掉“獲取”,它將起作用。 要么,或者如果我使用下面的代碼完全鎖定了獲取代碼,那么它將起作用:

    boost::upgrade_lock<boost::shared_mutex> schemaLock(schemaAccess);
    boost::upgrade_to_unique_lock<boost::shared_mutex> schemaUniqueLock(schemaLock);

我似乎無法理解為什么會這樣。 當我在哈希映射中寫入該鍵時,我將其鎖定,而當我讀取它時,編寫者不應該進入並破壞內存,是嗎?

您是否也嘗試鎖定get()並檢查問題是否消失了? 從高級的角度來看,只要沒有寫入,就不需要鎖定讀取。 如果有一些寫該位置的線程,則還需要保護讀操作,否則存在爭用情況(get()可能最終使用不再有效的東西)。

好的,我看到了對get()的鎖定可以解決此問題的編輯,因此確實如此。

事實是,不變的內存並發讀取不需要鎖定。 但是,如果存在並發寫入,則還需要鎖定讀取(相對於寫入,否則可能會發生各種奇怪的事情,例如部分/交錯讀取等)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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