c/c++ 多線程 unique_lock的使用


多線程 unique_lock的使用

unique_lock的特點:

1,靈活。可以在創建unique_lock的實例時,不鎖,然后手動調用lock_a.lock()函數,或者std::lock(lock_a, …),來上鎖。當unique_lock的實例被析構時,會自動調用unlock函數,釋放鎖。

unique_lock<mutex> lock_a(d1.m, std::defer_lock);

2,unique_lock的實例可以調用unlock函數。這個意味着,在unique_lock的實例銷毀前,你可以有選擇的在程序的分支釋放鎖。持有鎖的時間比所需時間更長,可能會導致性能下降,因為其他等待該鎖的線程,被阻止運行的時間超過了所需的時間。

注意:有個弊端,當不擁有鎖的時候,調用了unlock成員方法,程序崩潰。崩潰信息如下:

terminate called after throwing an instance of 'std::system_error'
  what():  Operation not permitted
Aborted (core dumped)

3,可以在作用域之間轉移鎖的所有權。右值的話,會自動被轉移;左值的話,必須手動調用std::move()函數,來進行鎖的所有權的轉移。

通常使用這種模式,是在待鎖定的互斥元依賴於程序的當前狀態,或者依賴於傳遞給返回std::unique_lock對象的函數的地方。

例子:關於上述第一點和第二點的

#include <list>
#include <iostream>
#include <mutex>
#include <algorithm>
#include <thread>
#include <unistd.h>

using namespace std;
class data_protect;
void swap(data_protect& , data_protect& );
//是線程安全的
class data_protect{
  friend void swap(data_protect& , data_protect& );
private:
  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 swap(data_protect& d1, data_protect& d2){
  //if(d1 == d2) return;

  //造成死鎖
  //d1.add_list(11);
  unique_lock<mutex> lock_a(d1.m, std::defer_lock);
  unique_lock<mutex> lock_b(d2.m, std::defer_lock);
  std::lock(lock_a, lock_b);
  swap(d1.alist, d2.alist);

  //有unlock成員函數,並可以手動調用unlock函數
  //如果沒有持有鎖,就調用unlock成員函數就會導致程序崩潰。所以要檢查是否擁有鎖。
  if(lock_a.owns_lock() && lock_b.owns_lock()){
    lock_a.unlock();
    lock_b.unlock();
  }
}
int main(){
  data_protect d1, d2;
  swap(d1, d2);
  d2.add_list(11);
}

github源代碼

例子:關於上述的第三點

#include <mutex>

std::unique_lock<std::mutex> getlock(){
  std::mutex sm;
  std::unique_lock<std::mutex> lk(sm);
  //prepare_data();
  return lk;//因為lk是右值,所以自動調用了std::move函數,把鎖的所有權轉移了出去。
}

void process_data(){
  std::unique_lock<std::mutex> lk(getlock());
  //do_something();
}

int main(){
  process_data();
}

github源代碼

c/c++ 學習互助QQ群:877684253

本人微信:xiaoshitou5854


免責聲明!

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



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