• c/c++ 多线程 mutex的理解


    多线程 mutex的理解

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

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

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

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

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

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

    #include <list>
    #include <iostream>
    #include <mutex>
    #include <algorithm>
    #include <thread>
    #include <unistd.h>
    
    using namespace std;
    
    class data_protect{
    public:
      list<int> alist{1,2};
      mutex m;
      mutex m1;
    public:
      
      void add_list(int val){
        m.lock();  //----------------①
        alist.push_back(val);
      }
      bool contains(int val){
        m1.unlock();//----------------------②
        return find(alist.begin(), alist.end(), val) != alist.end();
      }
    };
    
    void func(data_protect& dp){
      dp.add_list(12);
    }
    
    int main(){
      data_protect dp;
      thread t(func, ref(dp));
      //t.join();
      t.detach();//---------------③
      //sleep(1);
      dp.add_list(12);//----------------④
      if(dp.contains(12)){//------------------⑤
        cout << "contains 12" << endl;
      }
      for(auto& s : dp.alist){
        cout << s << endl;
      }
      pthread_exit(NULL);
    
    }
    
    

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

    执行结果分析:

    从③处开始就开了一个新的线程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>,它的好处是,即使发生了异常也能自动解锁。

    例子:

    #include <list>
    #include <iostream>
    #include <mutex>
    #include <algorithm>
    #include <thread>
    #include <unistd.h>
    
    using namespace std;
    
    class data_protect{
    public:
      list<int> alist{1,2};
      mutex m;
    public:
      
      void add_list(int val){
        lock_guard<mutex> g(m);
        alist.push_back(val);
      }
      bool contains(int val){
        lock_guard<mutex> g(m);
        return find(alist.begin(), alist.end(), val) != alist.end();
      }
    };
    
    void func(data_protect& dp){
      dp.add_list(12);
    }
    
    int main(){
      data_protect dp;
      thread t(func, ref(dp));
      //t.join();
      t.detach();
      //sleep(1);
      dp.add_list(12);
      if(dp.contains(12)){
        cout << "contains 12" << endl;
      }
      for(auto& s : dp.alist){
        cout << s << endl;
      }
      pthread_exit(NULL);
    
    }
    
    

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

    本人微信:xiaoshitou5854

  • 相关阅读:
    SecureCRT远程控制ubuntu
    zedboard启动过程分析
    zedboard之ubuntu环境变量设置
    理解 pkg-config 工具
    linux下 tar解压 gz解压 bz2等各种解压文件使用方法
    zedboard搭建交叉编译环境
    一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计
    zedboard 中SDK 修改串口设置(波特率。。。。)
    VC 2010下安装OpenCV2.4.4
    VS2010恢复默认编辑环境的设置
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9880228.html
Copyright © 2020-2023  润新知