经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C » 查看文章
c/c++ 多线程 mutex的理解
来源:cnblogs  作者:小石王  时间:2018/10/31 9:05:19  对本文有异议

多线程 mutex的理解

mutex,我的理解是每个mutex对象都是一个带锁头的门,这个门有两个状态,门开着和门关着,感觉像是废话。。。

当想查看门的里东西,或者把东西放进门里,或者从门里拿出东西前,都需要看看,门是否是打开的。

  • 如果门是打开的,就要进去后赶紧把门关上。关上后,就可以查看屋子里的东西,放东西到屋子里,从屋子里拿东西。
  • 如果门是关着的,就要在外面等着,直到有人出来时,把门打开了,你才能进去。

每个mutex都是不同的门,当你用mutex a锁上了一个门,就只能用mutex a去打开,用mutex b是打不开,切记。

例子:用mutex a锁门,用metex b去开门,结果没打开,就导致了程序的死锁。

注意:这个程序专门为了测试,mutex的问题。

  1. #include <list>
  2. #include <iostream>
  3. #include <mutex>
  4. #include <algorithm>
  5. #include <thread>
  6. #include <unistd.h>
  7. using namespace std;
  8. class data_protect{
  9. public:
  10. list<int> alist{1,2};
  11. mutex m;
  12. mutex m1;
  13. public:
  14. void add_list(int val){
  15. m.lock(); //----------------①
  16. alist.push_back(val);
  17. }
  18. bool contains(int val){
  19. m1.unlock();//----------------------②
  20. return find(alist.begin(), alist.end(), val) != alist.end();
  21. }
  22. };
  23. void func(data_protect& dp){
  24. dp.add_list(12);
  25. }
  26. int main(){
  27. data_protect dp;
  28. thread t(func, ref(dp));
  29. //t.join();
  30. t.detach();//---------------③
  31. //sleep(1);
  32. dp.add_list(12);//----------------④
  33. if(dp.contains(12)){//------------------⑤
  34. cout << "contains 12" << endl;
  35. }
  36. for(auto& s : dp.alist){
  37. cout << s << endl;
  38. }
  39. pthread_exit(NULL);
  40. }

执行结果:死锁,程序永远在等待锁的打开。

执行结果分析:

从③处开始就开了一个新的线程a,线程a调用了add_list()方法,add_list方法里,在①处是用m去上的锁。main函数线程在④处也调用了,add_list()方法,进去后,发现是上锁的状态,所以就阻塞在哪里,等着锁打开后,main函数线程好进去,然后在⑤处调用了contains方法,contains方法试图在②处用m1去解m的锁,所以就解不开①处的锁,所以就导致了一个线程一直等在①处的锁的地方,就导致了死锁。

如果把②处的m1.unlock();换成m.unlock();就能解开锁了,就不会导致死锁。

想说明的东西,用哪个mutex上的锁,就得用哪个mutex去解锁。

mutex的正确使用方法:不是直接用调用mutex的lock,unlock方法。理由是在lock和unlock中间的某段代码如果崩溃掉,就会导致unlock方法没有被执行,也就导致了,锁没有解开,别线程再来访问时,就变成了死锁。

所以使用:std::lock_guard<std::mutex>,它的好处是,即使发生了异常也能自动解锁。

例子:

  1. #include <list>
  2. #include <iostream>
  3. #include <mutex>
  4. #include <algorithm>
  5. #include <thread>
  6. #include <unistd.h>
  7. using namespace std;
  8. class data_protect{
  9. public:
  10. list<int> alist{1,2};
  11. mutex m;
  12. public:
  13. void add_list(int val){
  14. lock_guard<mutex> g(m);
  15. alist.push_back(val);
  16. }
  17. bool contains(int val){
  18. lock_guard<mutex> g(m);
  19. return find(alist.begin(), alist.end(), val) != alist.end();
  20. }
  21. };
  22. void func(data_protect& dp){
  23. dp.add_list(12);
  24. }
  25. int main(){
  26. data_protect dp;
  27. thread t(func, ref(dp));
  28. //t.join();
  29. t.detach();
  30. //sleep(1);
  31. dp.add_list(12);
  32. if(dp.contains(12)){
  33. cout << "contains 12" << endl;
  34. }
  35. for(auto& s : dp.alist){
  36. cout << s << endl;
  37. }
  38. pthread_exit(NULL);
  39. }

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号