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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM