欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-25 21:40:27
多线程 mutex的理解 mutex,我的理解是每个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

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

本人微信:xiaoshitou5854