当我在 MSVC 2012 中单步执行以下代码时 我在第 3 行和第 8 行放置了一个断点。
第一个中断出现在第 8 行。
lock_guard 被调用得很好,然后我们在第 3 行中断。 这次,由于已经获得了锁,所以当我跨过去时会抛出异常。
我真的希望它继续前进,因为它仍然是同一个线程调用(我们刚刚来自第 11 行。)
还有其他更适合这种情况的锁定机制吗?
我有 native win32 编程背景,所以我习惯了 WaitForSingleObject,它会让我毫不费力地通过这里, 但 lock_guard 没有。
我应该处理异常吗?我见过的所有示例都没有任何类型的 lock_guard 异常处理程序...
有没有一种更好的方法来确保 map 一次不会被多个线程访问? 我需要对其进行写入和读取锁定,并且 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
。
但是,您有一个更大的问题:您的访问器在返回用于分配映射元素的引用之前解锁互斥锁,因此分配本身不 protected 。这可以通过编写一个“setter”函数来解决,该函数在返回之前进行赋值;或者通过返回一个包含在其析构函数中释放的互斥锁的代理对象。解决这个问题可能会消除对 recursive_mutex
的需要。
关于c++ - 如何使用 std::lock_guard 锁定对 std::map 的读写访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12100937/