日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++——互斥量

發布時間:2024/4/17 c/c++ 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++——互斥量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、基本知識
  • 二、獨占互斥量mutex
    • 1.mutex的介紹
    • 2.mutex的成員函數
    • 3.實例演示
  • 三、lock_guard和unique_lock的使用和區別
  • 四、遞歸互斥量recursive_mutex
    • 1.基本知識
    • 2.演示示例
  • 五、帶超時的互斥量std::timed_mutex和std::recursive_timed_mutex


一、基本知識

C++11提供如下4種語義的互斥量(mutex)
std::mutex,獨占的互斥量,不能遞歸使用。
std::time_mutex,帶超時的獨占互斥量,不能遞歸使用。
std::recursive_mutex,遞歸互斥量,不帶超時功能。
std::recursive_timed_mutex,帶超時的遞歸互斥量。
使用時需要包含頭文件

#include<mutex>

二、獨占互斥量mutex

1.mutex的介紹

下面以 std::mutex 為例介紹 C++11 中的互斥量用法。
std::mutex 是C++11 中最基本的互斥量,std::mutex 對象提供了獨占所有權的特性——即不支持遞歸地對 std::mutex 對象上鎖,而 std::recursive_lock 則可以遞歸地對互斥量對象上鎖。

2.mutex的成員函數

構造函數:std::mutex不允許拷貝構造,也不允許 move 拷貝,最初產生的 mutex 對象是處于unlocked 狀態的。
lock():調用線程將鎖住該互斥量。線程調用該函數會發生下面 3 種情況:
①如果該互斥量當前沒有被鎖住,則調用線程將該互斥量鎖住,直到調用 unlock之前,該線程一直擁有該鎖。
② 如果當前互斥量被其他線程鎖住,則當前的調用線程被阻塞住。
③如果當前互斥量被當前調用線程鎖住,則會產生死鎖。
unlock(): 解鎖,釋放對互斥量的所有權。
try_lock():嘗試鎖住互斥量,如果互斥量被其他線程占有,則當前線程也不會被阻塞。線程調用該函數也會出現下面 3 種情況:這些
①如果當前互斥量沒有被其他線程占有,則該線程鎖住互斥量,直到該線程調用 unlock 釋放互斥量。
②如果當前互斥量被其他線程鎖住,則當前調用線程返回
false,而并不會被阻塞掉。
③如果當前互斥量被當前調用線程鎖住,則會產生死鎖。

3.實例演示

#include<iostream> #include<mutex> #include<thread> using namespace std;std::mutex mtx; int counter;void pthread_fun() {for (int i = 0; i < 10000; i++){mtx.lock();counter++;mtx.unlock();} }int main() {thread pthread[10];for (int i = 0; i < 10; i++){pthread[i] = thread(pthread_fun);}for (int i = 0; i < 10; i++){pthread[i].join();}cout << counter << endl;return 0; }

運行結果:

三、lock_guard和unique_lock的使用和區別

相對于手動lock和unlock,我們可以使用RAII(通過類的構造析構)來實現更好的編碼方式。
這里涉及到unique_lock,lock_guard的使用。
C++相較于C引入了很多新的特性, 比如可以在代碼中拋出異常, 如果還是按照以前的加鎖解鎖的話代碼會極為復雜繁瑣。

unique_lock,lock_guard的區別:
unique_lock與lock_guard都能實現自動加鎖和解鎖,但是前者更加靈活,能實現更多的功能。
unique_lock可以進行臨時解鎖和再上鎖,如在構造對象之后使用lck.unlock()就可以進行解鎖,lck.lock()進行上鎖,而不必等到析構時自動解鎖。

#include<iostream> #include<mutex> #include<thread> using namespace std;std::mutex mtx; int counter;void pthread_fun() {for (int i = 0; i < 10000; i++){//mtx.lock();error,必須和unlock配對,否則鎖得不到釋放std::unique_lock<mutex>lck(mtx);//right 這句語句執行會自動上鎖,生存期到了之后會調動析構函數自動釋放鎖counter++;//lck.unlock();//可以手動釋放,也可以等過了作用域,lck調用析構函數析構自動釋放鎖} }int main() {thread pthread[10];for (int i = 0; i < 10; i++){pthread[i] = thread(pthread_fun);}for (int i = 0; i < 10; i++){pthread[i].join();}cout << counter << endl;return 0; }

對于locak_guard來說,unique_lock顯得比較靈活一點,因為在lock_guard和unique_lock都可以借用對象有生存期調用析構函數釋放鎖的情況下,unique_lock可以還自己上鎖釋放鎖,顯得比較靈活一點,所以平時比較經常使用unique_lock。

四、遞歸互斥量recursive_mutex

1.基本知識

遞歸鎖允許同一個線程多次獲取該互斥鎖,可以用來解決同一線程需要多次獲取互斥量時死鎖的問題。
雖然遞歸鎖能解決這種情況的死鎖問題,但是盡量不要使用遞歸鎖,主要原因如下:
(1)需要用到遞歸鎖的多線程互斥處理本身就是可以簡化的,允許遞歸很容易放縱復雜邏輯的產生,并且產生晦澀,當要使用遞歸鎖的時候應該重新審視自己的代碼是否一定要使用遞歸鎖;
(2)遞歸鎖比起非遞歸鎖,效率會低;
(3)遞歸鎖雖然允許同一個線程多次獲得同一個互斥量,但可重復獲得的最大次數并未具體說明,一旦超過一定的次數,再對lock進行調用就會拋出std::system錯誤。

2.演示示例

#include<iostream> #include<mutex> #include<thread> using namespace std;std::recursive_mutex rc_mtx;//可遞歸的鎖 std::mutex mtx; int g_val = 0;void fun(int&& x) {if (x == 0) return;std::unique_lock<std::recursive_mutex>lck(rc_mtx);//right//下面語句error 會造成死鎖,因為遞歸的時候鎖沒有釋放,再次獲得鎖,造成死鎖。//std::unique_lock<std::mutex>lck(mtx);g_val++;x--;fun(std::move(x)); }int main() {std::thread pthreads[5];for (int i = 0; i < 5; i++){pthreads[i] = std::thread(fun, 5);}for (int i = 0; i < 5; i++){pthreads[i].join();}cout << g_val << endl;return 0; }

運行結果:

五、帶超時的互斥量std::timed_mutex和std::recursive_timed_mutex

std::timed_mutex比std::mutex多了兩個超時獲取鎖的接口:
try_lock_for:獲取鎖的時間,過了這個時間會釋放鎖
try_lock_until:嘗試獲得鎖,直到過了某個時間,返回false。

#include<iostream> #include<mutex> #include<thread> using namespace std;std::mutex mtx; std::timed_mutex t_mtx; int g_val = 0;//如果fun寫成下面那樣會發生死鎖,因為第一個獲取鎖的線程沒有釋放鎖,其他線程都會阻塞住 /* void fun() {mtx.lock();g_val++; } */std::chrono::milliseconds timeout(1000);void fun() {t_mtx.try_lock_for(timeout);//獲取鎖1000毫秒,1000毫秒后會釋放鎖g_val++; }int main() {std::thread pthreads[5];for (int i = 0; i < 5; i++){pthreads[i] = std::thread(fun);}for (int i = 0; i < 5; i++){pthreads[i].join();}cout << g_val << endl;return 0; }

總結

以上是生活随笔為你收集整理的C++——互斥量的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。