一、互斥量(mutex)的基本概念
- 互斥量就是个类对象,可以理解为一把锁,多个线程尝试用lock()成员函数来加锁,只有一个线程能锁定成功,如果没有锁成功,那么流程将卡在lock()这里不断尝试去锁定。
- 互斥量使用要小心,保护数据不多也不少,少了达不到效果,多了影响效率。
二、互斥量的用法
2.1 lock(),unlock()
- 添加头文件:
#include<mutex> - 声明与创建:
std::mutex my_mutex; - 先
lock()—>操作共享数据—>unlock()(这类错误很难排查)
lock()和unlock()务必要成对使用
//函数void inMsgRecvQueue()加锁片段:
my_mutex.lock();
msgRecvQueue.push_back(i);
my_mutex.unlock();
//函数outMsgLULProc(int& command)加锁片段:
my_mutex.lock();
if (!msgRecvQueue.empty())
{
//命令队列不为空
int command = msgRecvQueue.front();//得到第一条命令
msgRecvQueue.pop_front();//移除刚取出命令
my_mutex.unlock();//每一个分支出口处都需要解锁unlock()
return true;
}
my_mutex.unlock();//每一个分支出口处都需要解锁unlock()
return false;
2.2 std::lock_guard()
直接取代lock()和unlock(),使用std::lock_guard()后不能再使用lock()和unlock()
luck_guard()原理: lock_guard()是类模板,当在函数中创建局部类模板实例的时候,在构造函数中执行lock(),当函数运行结束后,在在析构函数中执行unlock()。
使用lock_guard()替换:
//函数void inMsgRecvQueue()加锁片段:
std::lock_guard<std::mutex>myLockGuard(my_mutex);
//my_mutex.lock();
msgRecvQueue.push_back(i);
//my_mutex.unlock();
//函数outMsgLULProc(int& command)加锁片段:
std::lock_guard<std::mutex>myLockGuard(my_mutex);
//my_mutex.lock();
if (!msgRecvQueue.empty())
{
//命令队列不为空
int command = msgRecvQueue.front();//得到第一条命令
msgRecvQueue.pop_front();//移除刚取出命令
//my_mutex.unlock();
return true;
}
//my_mutex.unlock();
return false;
三、死锁
一个互斥量(mutex)即为一把锁,死锁由至少两个互斥量产生。
3.1 死锁演示:
//函数void inMsgRecvQueue()加锁片段:
my_mutex1.lock();
my_mutex2.lock();
msgRecvQueue.push_back(i);
my_mutex2.unlock();
my_mutex1.lock();
//函数outMsgLULProc(int& command)加锁片段:
my_mutex2.lock();
my_mutex1.lock();
if (!msgRecvQueue.empty())
{
//命令队列不为空
int command = msgRecvQueue.front();//得到第一条命令
msgRecvQueue.pop_front();//移除刚取出命令
my_mutex1.lock();
my_mutex2.lock();
return true;
}
my_mutex1.lock();
my_mutex2.lock();
return false;
3.2 死锁一般解决方案:
- 多个锁
lock()顺序一致
3.3 std::lock()函数模板: 一次可锁住至少一个互斥量。(不存在多个锁出现死锁状况)谨慎使用
要么都锁,要么都不锁,只要有一个锁不住就都马上解锁,防止死锁产生。
使用方式:std::lock(my_mutex1,my_mutex2);
3.4 使用std::lock()配合lock_guard()防止忘记解锁:
std::lock(my_mutex1, my_mutex2);
std::lock_guard<std::mutex> my_lock_guard(my_mutex1, std::adopt_lock);
std::lock_guard<std::mutex> my_lock_guard(my_mutex2, std::adopt_lock);
msgRecvQueue.push_back(i);
std::adopt_lock表示该锁已经锁上,不需要在lock_guard()再次上锁。
更多内容欢迎参见我的个人网站:http://www.huazhige.online/
版权声明:本文为weixin_45983489原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。