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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C++ 多线程:条件变量 std::condition_variable

發布時間:2023/11/27 生活经验 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 多线程:条件变量 std::condition_variable 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 描述
      • 使用

描述

  • 頭文件<condition_variable>

  • 定義 class condition_variable;

  • 簡介
    之前我們也已經介紹過了C++多線程中互斥變量存在,已經足夠支持多線程中對共享普通系統數據的合理訪問。但是因為多線程中同一時刻必然會有一個線程持有鎖,一個線程等待鎖。而在代碼中使用while方式的循環等待必然會導致系統效率降低,cpu被無用消耗。
    查看如下代碼

    #include <iostream>
    #include <thread>
    #include <string>
    #include <mutex>
    #include <deque> //包含deque的頭文件
    using namespace std;std::mutex mu;
    std::deque<int> q; //全局共享數據,雙端隊列void function_1(){int count = 100;while (count > 0) {std::unique_lock<std::mutex> locker(mu);q.push_back(count);locker.unlock();std::this_thread::sleep_for(std::chrono::seconds(1));count--;}
    }void function_2() {int data = 0;while (data != 1) {std::unique_lock<std::mutex> locker(mu);//獲取到鎖之后檢測全局共享隊列是否為空,如果不為空則執行出隊操作if (!q.empty()) { data=q.back();q.pop_back();locker.unlock();std::cout << "t2 got a value from t1 " << data << std::endl; } else {//如果為空,則嘗試解鎖locker.unlock();//防止消耗cpu//std::this_thread::sleep_for(std::chrono::seconds(1)); }}
    }
    int main()
    {std::thread t1(function_1);std::thread t2(function_2);t1.join();t2.join();return 0;
    }
    

    由以上代碼可以很明顯得看出來t1線程提供數據push_back(生產者),t2線程消費數據pop_back(消費者),這兩個線程最合理得運行方式應該為生產者生產好數據,然后喚醒消費者去消費,消費完成之后繼續休眠。

    但是在t2線程如果檢測到全局隊列為空,則會嘗試解鎖,但是在t1線程向全局隊列push數據的時候t2線程仍然在嘗試解鎖,這樣的操作會導致系統cpu資源被無端消耗,即消費者一直在等待著生產者生產。
    這個時候我們的條件變量即可出山,它能夠比sleep_for函數使用起來更靈活

使用

在解決以上問題之前,先介紹幾個條件變量包含的成員函數

  • std::condition_variable::notify_onestd::condition_variable::notify_one通知一個等待線程,同時改函數作用在當前條件變量上
  • std::condition_variable::wait()導致當前線程阻塞直至條件變量被通知
    wait( std::unique_lock<std::mutex>)函數的實現方式是先原子解鎖線程,將當前線程加入到線程的等待執行列表,當notify_one或者notify_all解鎖阻塞線程之后,等待列表中的線程繼續執行完畢,并重新加鎖,最后退出wait()
    調用此函數之前必須保證當前函數已經被鎖定,且這里使用的鎖需為unique_lock,因為只有unique_lock才能夠支持同一個線程的重復加解鎖。
  • std::condition_variable::wait_for它的等待方式和wait的區別是增加了一個等待的時間,即除了等待notify_one解鎖之外還會有一個時間閾值,當到了這個時間閾值時仍然會退出。wait_for( std::unique_lock<std::mutex>& lock, const std::chrono::duration<Rep, Period>& rel_time)

根據以上條件變量的成員函數,修改代碼如下:

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <deque>
#include <condition_variable>
using namespace std;std::mutex mu;
std::deque<int> q;
std::condition_variable cond;
/*
線程1使用了 notify_one函數,來用作通知等待線程處理事務。
*/
void function_1(){int count = 100;while (count > 0) {std::unique_lock<std::mutex> locker(mu);q.push_back(count);locker.unlock();cond.notify_one();//如果環境中有多個等待線程,可以使用`notify_all()`同時觸發std::this_thread::sleep_for(std::chrono::seconds(1));count--;}
}
/*
線程2是等待線程,且為了防止偽激活,這里等待線程同時加入了 lamda表達式來標示當
全局隊列q也為空的時候線程2仍然處于等待狀態。否則偽激活又會像上一套代碼中的else
處理解鎖消耗系統資源。
*/
void function_2() {int data = 0;while (data != 1) {std::unique_lock<std::mutex> locker(mu);cond.wait(locker,[](){return !q.empty();});data=q.back();q.pop_back();locker.unlock();std::cout << "t2 got a value from t1 " << data << std::endl; }
}
int main()
{std::thread t1(function_1);std::thread t2(function_2);t1.join();t2.join();return 0;
}

輸出如下

t2 got a value from t1 100
t2 got a value from t1 99
t2 got a value from t1 98
t2 got a value from t1 97
t2 got a value from t1 96
t2 got a value from t1 95
...
...

參考文章:
https://en.cppreference.com/w/cpp/thread/condition_variable
https://zh.cppreference.com/w/cpp/thread/condition_variable/

總結

以上是生活随笔為你收集整理的C++ 多线程:条件变量 std::condition_variable的全部內容,希望文章能夠幫你解決所遇到的問題。

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