C++多线程快速入门(三):生产者消费者模型与条件变量使用
互斥鎖完成
#include <iostream> #include <deque> #include <thread> #include <mutex>std::deque<int> q; std::mutex mtx;static void produce(int val) {while(val--) {std::unique_lock<std::mutex> guard(mtx);q.push_front(val);mtx.unlock();std::this_thread::sleep_for(std::chrono::seconds(1));} } static void consumer() {int data = INT_MAX;while(data != 0) {std::unique_lock<std::mutex> guard(mtx);if (!q.empty()) {data = q.back();q.pop_back();std::cout << data << std::endl;mtx.unlock();} else {mtx.unlock();}} } void test() {std::thread t1(produce,3);std::thread t2(consumer);t1.join();t2.join(); }int main() {test();return 0; }效果如下:
9 8 7 6 5 4 3 2 1 0 Process finished with exit code 1produce在生產(chǎn)過程中,std::this_thread::sleep_for (std::chrono::seconds(1));表示延時1s,所以生產(chǎn)過程很慢。
consumer存在著一個while循環(huán),只有在接收到表示結(jié)束的數(shù)據(jù)的時候,才會停止,每次循環(huán)內(nèi)部,都是先加鎖,判斷隊列不空,然后就取出一個數(shù),最后解鎖。這樣其實做了很多無用功,并且CPU占用率很高
可以在consumer內(nèi)部也加一個小延時,在一次判斷后,如果發(fā)現(xiàn)隊列是空的,那就懲罰一下自己,延時一下,減少CPU的占用率。
條件變量改進模型
c++11提供了#include <condition_variable>頭文件,std::condition_variable可以和std::mutex結(jié)合一起使用,其中有兩個重要的接口,notify_one()和wait()。
wait()可以讓線程陷入休眠狀態(tài),在消費者生產(chǎn)者模型中,如果生產(chǎn)者發(fā)現(xiàn)隊列中沒有東西,就可以讓自己休眠.notify_one()就是喚醒處于wait中的其中一個條件變量.
那什么時刻使用notify_one()比較好呢,當然是在生產(chǎn)者往隊列中放數(shù)據(jù)的時候了,隊列中有數(shù)據(jù),就可以趕緊叫醒等待中的線程起來干活了。
下面是主要修改代碼:
此時CPU的占用率也很低,因為在消費者端,隊列為空時,將控制權(quán)交給了cpu,直到被喚醒。
需要注意的是在判斷隊列是否為空的時候,使用的是while(q.empty()),而不是if(q.empty())
這是因為wait()從阻塞到返回,不一定就是由于notify_one()函數(shù)造成的,還有可能由于系統(tǒng)的不確定原因喚醒(可能和條件變量的實現(xiàn)機制有關(guān)),這個的時機和頻率都是不確定的,被稱作偽喚醒,如果在錯誤的時候被喚醒了,執(zhí)行后面的語句就會錯誤,所以需要再次判斷隊列是否為空,如果還是為空,就繼續(xù)wait()阻塞。
在管理互斥鎖的時候,使用的是std::unique_lock而不是std::lock_guard,在上一篇筆記C++多線程快速入門(二)共享數(shù)據(jù)同步以及數(shù)據(jù)競爭中,談到過ock_guard沒有l(wèi)ock和unlock接口,而unique_lock提供了。這里的話也是由于此點原因。因為在wait()函數(shù)之前,使用互斥鎖保護了,如果wait的時候什么都沒做,豈不是一直持有互斥鎖?那生產(chǎn)者也會一直卡住,不能夠?qū)?shù)據(jù)放入隊列中了。所以,wait()函數(shù)會先調(diào)用互斥鎖的unlock()函數(shù),然后再將自己睡眠,在被喚醒后,又會繼續(xù)持有鎖,保護后面的隊列操作。
另外除了notify_one()函數(shù),c++還提供了notify_all()函數(shù),可以同時喚醒所有處于wait狀態(tài)的條件變量。
參考
https://blog.csdn.net/qq_43145072/article/details/103732176
往期內(nèi)容回顧
C++多線程快速入門(二)共享數(shù)據(jù)同步以及數(shù)據(jù)競爭
C++多線程快速入門(一):基本&常用操作
總結(jié)
以上是生活随笔為你收集整理的C++多线程快速入门(三):生产者消费者模型与条件变量使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 商业计划书多少钱啊?
- 下一篇: C++多线程快速入门(四)shared_