簡體   English   中英

如何使用std :: lock_guard鎖定對std :: map的讀寫訪問權限?

[英]How do I use std::lock_guard to lock read and write access to a std::map?

當我在MSVC 2012中逐步執行以下代碼時,在第3行和第8行上放置一個斷點。

第一個中斷出現在第8行。

調用lock_guard就好了,然后我們在第3行中斷。這次,因為已經獲得了鎖,所以當我越過時會引發異常。

我真的希望它繼續前進,因為它仍然是相同的線程調用(我們只是來自第11行)。

是否存在另一個更適合這種情況的鎖定機制?

我有本機win32編程的背景,所以我習慣了WaitForSingleObject,它只會讓我順利進行,而lock_guard不會。

我應該處理例外嗎? 我見過的示例都沒有為lock_guard提供任何類型的異常處理程序...

有沒有一種更好的方法來確保一次不由多個線程訪問該映射? 我需要寫鎖定和讀鎖定,而lock_guard似乎是一種平滑的選擇,因為我不必使用ReleaseMutex ...

    //Cars.h
    mutable std::mutex carsMutex;
    class Cars
    {
    private:
        std::map<std::string,Cars> _cars;
    public:
        virtual ~Cars() {}
        Cars() {}
        Cars & operator[](const std::string &key);
        Cars & operator[](const DWORD &key);
        std::string color;
    };

    //Cars.cpp
      #include "Cars.h"
1.    Cars & Cars::operator[](const std::string &key)
2.    {
3.        std::lock_guard<std::mutex> lock_a(carsMutex);
4.        return _cars[key];
5.    }
6.    Cars & Cars::operator[](const DWORD &key)
7.    {
8.        std::lock_guard<std::mutex> lock_a(carsMutex);
9.        std::stringstream ss;
10.       ss << key;
11.       return operator[](ss.str());
12.   }
14.   void main()
15.   {
16.       //ok i have multiple threads like this one writing and reading from the map
17.       Cars cars;
18.       cars[(DWORD)2012]["volvo"].color = "blue";
19.   }

更新:這是我對上面代碼的編輯。 我已經考慮了答案,這是我正確嘗試使用std :: lock_guard的新嘗試,如果它不正確,請發表評論。

    //Cars.h
    mutable std::recursive_mutex carsMutex;
    class Cars
    {
    private:
        std::string _color;
        std::map<std::string,Cars> _cars;
    public:
        virtual ~Cars() {}
        Cars() {}
        Cars & operator[](const std::string &key);
        Cars & operator[](const DWORD &key);
        void color(const std::string &color);
        std::string color();
    };

       //Cars.cpp
       #include "Cars.h"
 1.    Cars & Cars::operator[](const std::string &key)
 2.    {
 3.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
 4.        return _cars[key];
 5.    }
 6.    Cars & Cars::operator[](const DWORD &key)
 7.    {
 8.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
 9.        std::stringstream ss;
10.        ss << key;
11.        return operator[](ss.str());
12.    }
13.    void color(const std::string &color)
14.    {
15.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
16.        _color = color;
17.    }
18.    std::string color()
19.    {
20.        std::lock_guard<std::recursive_mutex> lock(carsMutex);
21.        return _color;
22.    }
23.
24.    Cars cars;//this is global...
25.    void main()
26.    {
27.        //ok i have multiple threads like this one writing and reading from the map
28.        cars[(DWORD)2012]["volvo"].color("blue");
29.    }

要允許線程重新獲取它已經擁有的互斥鎖,您需要std::recursive_mutex而不是std::mutex

但是,您有一個更大的問題:訪問器返回用於分配map元素的引用之前會解鎖互斥鎖,因此分配本身不受保護。 可以通過編寫一個“ setter”函數在返回之前進行分配來解決此問題。 或返回包含在其析構函數中釋放的互斥鎖的代理對象。 解決此問題可能會消除對recursive_mutex的需要。

暫無
暫無

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

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