女人夜夜春高潮爽A∨片传媒_国产精品VIDEOS麻豆_在线精品亚洲一区二区三区_亚洲熟妇无码av

編程代碼
新聞詳情

C++11多線程編程(五)——生產消費者模型之條件變量

發布時間:2021-01-06 16:29:00 瀏覽(lan)次數(shu):2387

當某個(ge)線(xian)程(cheng)持有(you)這(zhe)把鎖的時候(hou)(就是(shi)所謂的加鎖),那(nei)么(me)這(zhe)個(ge)線(xian)程(cheng)是(shi)獨占所有(you)的資(zi)源,這(zhe)里的資(zi)源指的是(shi)執行的權限,其他要搶奪資(zi)源的線(xian)程(cheng)都不(bu)得不(bu)等待。在很多情況(kuang)下(xia),這(zhe)都容(rong)易(yi)適用,但是(shi)有(you)些(xie)情況(kuang)下(xia),卻會產生一些(xie)異(yi)常情況(kuang)。

在(zai)生產(chan)消費(fei)者模型當(dang)中,肯定都會用到(dao)互(hu)斥鎖(suo)的(de)(de)機制的(de)(de),當(dang)生產(chan)者往(wang)隊(dui)列中放數(shu)據(ju)的(de)(de)瞬間(jian),消費(fei)者是(shi)不能(neng)取數(shu)據(ju)的(de)(de),那這時候(hou)可(ke)能(neng)會碰見一個問題,如果生成者因(yin)為(wei)某些(xie)原因(yin),放數(shu)據(ju)過慢,但是(shi)消費(fei)者取數(shu)據(ju)很快,當(dang)隊(dui)列中沒(mei)有(you)數(shu)據(ju)了(le),消費(fei)者還去取的(de)(de)話,就會發生異常情況。有(you)些(xie)人(ren)可(ke)能(neng)會說,加個條(tiao)件(jian)判斷一下隊(dui)列是(shi)否(fou)為(wei)空(kong)不就可(ke)以了(le)。


這個肯定是(shi)當然可以(yi)的(de)(de),但是(shi)在(zai)隊列(lie)依舊沒(mei)有數(shu)據的(de)(de)這一段時間,是(shi)要(yao)不(bu)斷(duan)的(de)(de)循環判斷(duan)這個條件,CPU肯定是(shi)會飆升的(de)(de),浪費了(le)很多不(bu)必要(yao)的(de)(de)資源。

這(zhe)時候我們設(she)想,能(neng)否設(she)計這(zhe)樣(yang)的(de)一(yi)種(zhong)機制,如果(guo)在隊列沒(mei)有數據(ju)的(de)時候,消費者(zhe)線程(cheng)能(neng)一(yi)直阻塞在那(nei)里,等待(dai)著別人給它(ta)喚醒,在生產者(zhe)往隊列中放入(ru)數據(ju)的(de)時候通知(zhi)一(yi)下(xia)這(zhe)個等待(dai)線程(cheng),喚醒它(ta),告訴它(ta)可以來(lai)取數據(ju)了。

于是多線程中的條件(jian)變量就橫(heng)空出世!

條(tiao)件變量是(shi)(shi)多(duo)線程(cheng)數據同步的一種(zhong)操作,不(bu)管(guan)是(shi)(shi)用哪種(zhong)框架,哪種(zhong)語言實現多(duo)線程(cheng)的功能,條(tiao)件變量都(dou)是(shi)(shi)不(bu)得(de)不(bu)考慮的一種(zhong)情(qing)況(kuang)。C++中(zhong)提供了(le)#include <condition_variable>頭文件,里面就(jiu)包含了(le)條(tiao)件變量的相關類。其中(zhong)有(you)兩個非(fei)常重(zhong)要的接(jie)口,wait()和notify_one(),wait()可以讓線程(cheng)陷入休(xiu)眠(mian)狀態(tai),意思就(jiu)是(shi)(shi)不(bu)干活(huo)了(le),notify_one()就(jiu)是(shi)(shi)喚醒真(zhen)正(zheng)休(xiu)眠(mian)狀態(tai)的線程(cheng),開始干活(huo)了(le)。當然還有(you)notify_all()這(zhe)個接(jie)口,顧名(ming)思義(yi),就(jiu)是(shi)(shi)通知所有(you)正(zheng)在(zai)等待的線程(cheng),起(qi)來(lai)干活(huo)了(le)。

以下是代碼的實現部分

#include <iostream>
#include <deque>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
 
deque<int> q;
mutex mt;
condition_variable cond;
 
void thread_producer()
{
    int count = 10;
    while (count > 0)
    {
        unique_lock<mutex> unique(mt);
        q.push_front(count);
        unique.unlock();
        cout << "producer a value: " << count << endl;
        cond.notify_one();
        this_thread::sleep_for(chrono::seconds(1));
        count--;
    }
}
 
void thread_consumer()
{
    int data = 0;
    while (data != 1)
    {
        unique_lock<mutex> unique(mt);
        while (q.empty())
            cond.wait(unique);
        data = q.back();
        q.pop_back();
        cout << "consumer a value: " << data << endl;
        unique.unlock();
    }
}
 
int main()
{
    thread t1(thread_consumer);
    thread t2(thread_producer);
    t1.join();
    t2.join();
    return 0;
}

生產者:首先生產者利(li)用unique_lock來(lai)加(jia)鎖(suo),然后將(jiang)生產的數據放入隊列,打印,解鎖(suo),一旦解鎖(suo)之(zhi)后,消費者獲得了執行機會。

消費(fei)者(zhe):另一方面消費(fei)者(zhe)就會通(tong)過(guo)unique_lock獲得控制(zhi)權,也(ye)就是獲得鎖,然后判(pan)斷(duan)隊列(lie)為空的話就一直盜用(yong)wait()函(han)數阻塞在那里,等待其他(ta)線程(cheng)來喚醒(xing)它。而阻塞該(gai)線程(cheng)時,該(gai)函(han)數會自動解鎖,允許其他(ta)線程(cheng)執(zhi)行。

生產者(zhe)(zhe):再次(ci)回(hui)到生產者(zhe)(zhe)這里,生產者(zhe)(zhe)線(xian)程利用(yong)利用(yong)條件變量cond.notify_one()來通知阻塞(sai)的線(xian)程起來干活(huo)了。

消費者:阻塞在那里的(de)消費者線(xian)程一旦得到notify喚(huan)醒,該(gai)函數(shu)取(qu)消阻塞并(bing)獲取(qu)鎖(suo),然后取(qu)出隊列中(zhong)的(de)數(shu)據,并(bing)打(da)印(yin),最后解(jie)鎖(suo)。

生(sheng)產(chan)者(zhe)(zhe):再次回到生(sheng)產(chan)者(zhe)(zhe),然后(hou)生(sheng)產(chan)者(zhe)(zhe)休眠(mian)1秒(miao),這里(li)休眠(mian)是(shi)為(wei)了模擬生(sheng)產(chan)者(zhe)(zhe)生(sheng)產(chan)慢的情(qing)況,實際開發(fa)的時(shi)候不要去休眠(mian)。最后(hou)減一(yi),進入下一(yi)次生(sheng)產(chan)。

以上就(jiu)是利(li)用條件變量來實(shi)現生產消(xiao)費(fei)者模型,這個(ge)會大大降低CPU的占有率,當然代(dai)價就(jiu)是編程稍微有點麻煩(fan),但與這優化程序來比,這肯定(ding)是值的。

在(zai)線客服
客服電話
  • 0755-23712116
  • 13310869691