三亚网站外包,宁波seo教程行业推广,南山模板网站建设公司,网站建设参考文献外文C11并发与多线程笔记#xff08;5#xff09;互斥量概念、用法、死锁演示及解决详解 1、互斥量#xff08;mutex#xff09;的基本概念2、互斥量的用法2.1 lock()#xff0c;unlock()2.2 lock_guard类模板 3、死锁3.1 死锁演示3.2 死锁的一般解决方案#xff1a;3.3 std:… C11并发与多线程笔记5互斥量概念、用法、死锁演示及解决详解 1、互斥量mutex的基本概念2、互斥量的用法2.1 lock()unlock()2.2 lock_guard类模板 3、死锁3.1 死锁演示3.2 死锁的一般解决方案3.3 std::lock()函数模板3.4 std::lock_guard的std::adopt_lock参数 1、互斥量mutex的基本概念
互斥量就是个类对象可以理解为一把锁多个线程尝试用**lock()**成员函数来加锁只有一个线程能锁定成功如果没有锁成功那么流程将卡在lock()这里不断尝试去锁定。互斥量使用要小心保护数据不多也不少少了达不到效果多了影响效率。
2、互斥量的用法
包含#include mutex头文件
2.1 lock()unlock()
步骤如下 1. 引入头文件 2. 创建一个互斥量 3.在加锁位置先lock() 操作共享数据 unlock() 注意lock()和unlock()要成对使用 例1
#includeiostream
#includethread
#include vector
#includelist
#includemutex
using namespace std;class A {
public://把收到的消息玩家命令加入到一个队列的线程void inMsgRecvQueue() {for (int i 0; i 100000; i) {cout inMsgRecvQueue()执行插入一个元素 i endl;//cout只输出i不访问共享数据my_mutex.lock();msgRecvQueue.push_back(i);// 假设这个数字i就是收到的命令直接弄到消息队列里边来my_mutex.unlock();}}bool outMsgLULProc(int command) {my_mutex.lock();if (!msgRecvQueue.empty()) {//消息不为空command msgRecvQueue.front();//返回第一个元素但不检查元素是否存在msgRecvQueue.pop_front();//移除第一个元素但不返回my_mutex.unlock();//有分支退出就要加一个unlock与其对应return true;}my_mutex.unlock();return false;}//把数据从消息队列中取出的线程void outMsgRecvQueue() {int command 0;for (int i 0; i 100000; i) {bool result outMsgLULProc(command);if (result true) {cout outMsgRecvQueue()执行,取出一个元素 command endl;//可以进行命令数据处理}else {//消息队列为空cout outMsgRecvQueue()执行但目前消息队列中为空 i endl;}cout end endl;}}private:listint msgRecvQueue;//容器专门用于存放玩家发来的命令mutex my_mutex;//创建一个互斥量
};int main() {A myobja;//线程通过对象的成员函数时第二个参数需要是对象的地址因为成员函数运行时需要用到this指针thread mythreadInMsgRecv(A::inMsgRecvQueue, myobja);thread mythreadOutMsgRecv(A::outMsgRecvQueue, myobja);mythreadInMsgRecv.join();mythreadOutMsgRecv.join();cout I love China! endl;return 0;
}例2
#include iostream
#include thread
#include mutex
#include list
using namespace std;listint test_list;
mutex myMutex;//创建互斥量void in_list(){for(int num0;num10000;num){myMutex.lock();cout插入数据 numendl;test_list.push_back(num);myMutex.unlock();}}void out_list(){for(int num0;num10000; num){myMutex.lock();if(!test_list.empty()){int tmp test_list.front();test_list.pop_front();cout取出数据tmpendl;}myMutex.unlock();}
}
int main()
{thread in_thread(in_list);thread out_thread(out_list);in_thread.join();out_thread.join();cout Hello World! endl;return 0;
}
2.2 lock_guard类模板
lock_guard 对象名(myMutex);取代lock()和unlock()lock_guard 构造函数执行了mutex::lock();在作用域结束时调用析构函数执行mutex::unlock()可以通过添加{}来减小作用域
#include iostream
#include thread
#include mutex
#include list
using namespace std;listint test_list;
mutex myMutex;void in_list() {for (int num 0; num 10000; num) {{ //也可以多加一对括号减小作用域lock_guardmutex myGuard(myMutex); //创建lock_guard对象cout 插入数据 num endl;test_list.push_back(num);}}
}void out_list() {for (int num 0; num 10000; num) {lock_guardmutex myGuard(myMutex);if (!test_list.empty()) {int tmp test_list.front();test_list.pop_front();cout 取出数据 tmp endl;}}
}
int main()
{thread in_thread(in_list);thread out_thread(out_list);in_thread.join();out_thread.join();cout I love China! endl;return 0;
}3、死锁
3.1 死锁演示
死锁至少有两个互斥量mutex1mutex2。
线程A执行时这个线程先锁 mutex1并且锁成功了然后去锁mutex2的时候出现了上下文切换。上下文切换后线程B执行这个线程先锁mutex2因为mutex2没有被锁即mutex2可以被锁成功然后线程B要去锁mutex1.此时死锁产生了A锁着mutex1需要锁mutex2B锁着mutex2需要锁mutex1两个线程没办法继续运行下去。
3.2 死锁的一般解决方案
只要保证多个互斥量上锁的顺序一样就不会造成死锁。
3.3 std::lock()函数模板
std::lock(mutex1,mutex2……); 一次锁定多个互斥量一般这种情况很少用于处理多个互斥量。如果互斥量中一个没锁住它就等着等所有互斥量都锁住才能继续执行。如果有一个没锁住就会把已经锁住的释放掉要么互斥量都锁住要么都没锁住防止死锁破坏请求与保持条件资源一次性申请一次性释放
#include iostream
#include thread
#include mutex
#include list
using namespace std;listint test_list;
mutex myMutex1;
mutex myMutex2;void in_list() {for (int num 0; num 10000; num) {lock(myMutex1, myMutex2);//一次锁定多个互斥量cout 插入数据 num endl;test_list.push_back(num);myMutex2.unlock();myMutex1.unlock();}
}void out_list() {for (int num 0; num 10000; num) {lock(myMutex1, myMutex2);if (!test_list.empty()) {int tmp test_list.front();test_list.pop_front();cout 取出数据 tmp endl;}myMutex1.unlock();myMutex2.unlock();}
}
int main()
{thread in_thread(in_list);thread out_thread(out_list);in_thread.join();out_thread.join();cout I love China! endl;return 0;
}3.4 std::lock_guard的std::adopt_lock参数
采用std::lock函数和std::lock_guard 来联合使用
my_guard(my_mutex,std::adopt_lock); 加入adopt_lock后在调用lock_guard的构造函数时不再进行lock();adopt_guard为结构体对象起一个标记作用表示这个互斥量已经lock()不需要在lock()。
#include iostream
#include thread
#include mutex
#include list
using namespace std;listint test_list;
mutex myMutex1;
mutex myMutex2;void in_list() {for (int num 0; num 10000; num) {lock(myMutex1, myMutex2); //lock联合lock_guard使用lock_guardmutex mutex1(myMutex1, adopt_lock);lock_guardmutex mutex2(myMutex2, adopt_lock);cout 插入数据 num endl;test_list.push_back(num);}
}void out_list() {for (int num 0; num 10000; num) {lock(myMutex1, myMutex2);lock_guardmutex mutex1(myMutex1, adopt_lock);lock_guardmutex mutex2(myMutex2, adopt_lock);if (!test_list.empty()) {int tmp test_list.front();test_list.pop_front();cout 取出数据 tmp endl;}}
}
int main()
{thread in_thread(in_list);thread out_thread(out_list);in_thread.join();out_thread.join();cout I love China! endl;return 0;
}