queque队列mysql死锁_五、互斥量概念、用法、死锁

本文介绍了互斥量的概念、用法,并通过示例解释了死锁的产生及解决办法,同时提到了如何使用std::lock_guard避免忘记解锁导致的问题。
摘要由CSDN通过智能技术生成

一、互斥量mutex

保护共享数据,操作时,用代码把共享数据锁住,操作数据,解锁。其他线程要操作共享数据的线程必须等待解锁,锁住,操作,解锁。

互斥量就是类对象,一个锁,多个线程用lock()成员函数加锁这个锁头,只有一个线程能锁成功,成功的标志是lock函数返回,如果没有锁成功,那么流程就卡在lock()这里,不断的尝试去锁这个锁头。

互斥量使用要小心,保护数据多了,影响效率,保护少了,没达到保护效果。

二、互斥量用法

1、lock()、unlock()

include

先lock,操作共享数据,再unlock。

使用规则:成对使用,有lock必须有unlock;

1 #include

2 #include //线程

3 #include

4 #include

5 #include

6 /*

7 网络游戏服务器8 创建两个线程,一个线程收集玩家命令(用一个数字代表玩家命令),并把命令数据写到一个队列中;9 另一个线程从队列中取出玩家发送来的命令,解析,然后执行玩家需要的动作。10 list:频繁顺序插入和删除数据时效率高;11 vector:频繁随机插入和删除数据时效率高;12 准备使用成员函数来作为线程函数13 */

14 using namespacestd;15 classA{16 public:17 //把收到的消息(玩家命令)让入到一个队列中的线程函数

18 voidInMsgQue(){19 for(int i=0;i<100;i++){20 cout<

23 my_mutex.unlock();24 }25

26 }27 bool outMsgLULProc(int &command){//这样的目的是为了方便后序对command的操作28 my_mutex.lock();29 if(!MyQue.empty()){30 int command =MyQue.front();31 MyQue.pop_front();32 my_mutex.unlock();//这个unlock特别容易被忘记写33 return true;34 }35 my_mutex.unlock();36 return false;37 }38 //把数据从消息队列中取出来的线程函数

39 voidOutMsgQue(){40 int command=0;41 for(int i=0;i<100;i++){42 bool result =outMsgLULProc(command);43 if(result){44 //消息不空

45 cout<

47 }48 else{49 cout << "OutMsgQue执行,但是消息队列为空"<

52 }53 cout<

56 private:57 listMyQue;58 std::mutex my_mutex;//创建一个互斥量

59 };60

61 intmain(){62 A myobj;63 std::thread myout(&A::OutMsgQue,&myobj);64 std::thread myin(&A::InMsgQue,&myobj);//必须市引用,才能保证线程用的是同一个对象

65 myout.join();66 myin.join();67 cout<

2、std::lock_guard类模板

为了防止忘记unlock,引入lock_guard,类似于智能指针,他会帮你unlock。

1 bool outMsgLULProc(int &command){2 std::lock_guard<:mutex>guardd(my_mutex);3 if(!MyQue.empty()){4 int command =MyQue.front();5 MyQue.pop_front();6 return true;7 }8 return false;9 }

lock_guard构造函数执行了lock;析构函数执行了unlock。

只有return的时候才unlock,没有分开使用lock和unlock灵活。

可以用大括号提前结束guard:

1 voidInMsgQue(){2 for(int i=0;i<100;i++){3 cout<sbguard(my_mutex);6 MyQue.push_back(i);//假设i就是命令

7 }//大括号结束,lock_guard析构函数执行8 //其他处理代码、、、、、、、

9 }10

11 }

三、死锁

1、演示

举例:张三在北京等李四,不挪窝;李四在深圳等张三,不挪窝。

c++中:

死锁问题是有至少两个锁头也就是两个互斥量才会产生。

有两个锁:金锁,银锁

线程:A 和 B

线程A先锁金锁,金锁锁成功,然后去lock银锁。。。

线程B先锁银锁,银锁还没被锁的话,锁银锁成功了,然后去lock金锁。。。但是金锁被A锁了。。。

A拿不到银锁,金锁解不开,B去拿金锁,但是金锁被A锁了,所以银锁解不开。

这时就发生死锁了。AB两个线程就干等着直到永远~~

2、解决方案

只要保证两个互斥量的lock顺序一致,就不会发生死锁。

3、std::lock()函数模板

用来处理多个互斥量。

可以一次锁住两个或多个互斥量。

它不存在由于多个线程中因为锁的顺序问题导致的死锁。

如果一个锁没锁住,他就会马上解锁之前所有锁上的互斥量,然后在那儿等着,等所有的互斥量都能够锁住,它才能往下走。

要么都锁住,要么都没有锁住。

1 voidInMsgQue(){2 for(int i=0;i<100;i++){3 cout<

5 MyQue.push_back(i);//假设i就是命令

6 my_mutex1.unlock();7 my_mutex2.unlock();8 //其他处理代码、、、、、、、

9 }10

11 }

容易忘记unlock

4、std::lock_guard的std::adopt_lock参数

使用lock模板,还是容易忘记unlock,那么可是使用lock_guard的adopt_lock参数:

1 voidInMsgQue(){2 for(int i=0;i<100;i++){3 cout<

std::lock(my_mutex1,my_mutex2);4 std::lock_guard<:mutex> sbguard(my_mutex1,std::adopt_lock);5 std::lock_guard<:mutex> sbguard2(my_mutex2,std::adopt_lock);6 MyQue.push_back(i);//假设i就是命令7 //其他处理代码、、、、、、、

8 }9 }

这个参数就是起一个标记作用,就是如果互斥量已经被lock了,那就不会再调用lock_guard的构造函数了,就只剩析构函数了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值