当我在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. }
答案 0 :(得分:4)
要允许线程重新获取已有的互斥锁,您需要std::recursive_mutex
而不是std::mutex
。
但是,您遇到了一个更大的问题:您的访问者在返回您用于分配地图元素的引用之前解锁互斥锁,因此分配本身是无人看管的。这可以通过编写“setter”函数来修复,该函数在返回之前执行赋值;或者通过返回包含在其析构函数中释放的互斥锁的代理对象。解决此问题可能会消除对recursive_mutex
的需求。