天天看點

C++11 生産者消費者

下面是一個生産者消費者問題,來介紹condition_variable的用法。當線程間的共享資料發生變化的時候,可以通過condition_variable來通知其他的線程。消費者wait 直到生産者通知其狀态發生改變,Condition_variable是使用方法如下:

·當持有鎖之後,線程調用wait

·wait解開持有的互斥鎖(mutex),阻塞本線程,并将自己加入到喚醒隊列中

·當收到通知(notification),該線程從阻塞中恢複,并加入互斥鎖隊列(mutex queue)

 線程被喚醒之後繼續持有鎖運作。

Condition variable有兩種類型:condition_variable 和 condition_variable_any,前一種效率更高,但是使用不夠靈活,隻支援std::unique_lock<std::mutex>類型的互斥鎖;後一種比較靈活,支援所有類型的鎖,但是效率稍微低一些。

有一點需要注意的是使用condition variable進行通信的線程,condition variable 需要使用相同的互斥信号量(mutex)。

下面來看例子:(當按下Enter鍵之後停止)

C++11 生産者消費者
C++11 生産者消費者

運作結果:

C++11 生産者消費者

對程式進行一下說明,程式中有三個線程,主線程、生産者線程、消費者線程,三個線程之間亂序執行,通過一些全局變量來控制他們的執行順序。主線程的作用是控制生産消費過程是否結束,當程式運作之後,主線程通過getchar()接收一個輸入,接收到輸入後會将ArretDemande設定為true,另外兩個線程會終止。生産者線程将生産出來的資料放在一個queue類型的buffer中,并解鎖,通知消費之線程,buffer中最多“能”存10個資料,如果buffer中已經有10個資料還沒有被取走,則會通知消費者線程“消費”,如果ArretDmande被置位,則打開鎖,并通知消費之線程。消費者線程主要是将buffer中的資料取出來,當buffer為空的時候阻塞自己,并通知生産者線程,當ArretDemande被置位,且已經消費完産品則解鎖,并通知生産者線程。需要注意的是需要通信的生産者和消費者這兩個線程通過condition variable來實作通信,必須操作同一個mutex,這裡是lockbuffer,并且每次Notify都會打開目前鎖。

程式中對interlock進行的操作是原子的,interlock.fet_add(N),效果是将interlock加N,然後傳回interlock在加N之前的值,atomic類型是通過一定的記憶體順序規則來實作這個過程的。

雖然conditon_variable 隻能支援std::unique_lock<std::mutex>類型的互斥鎖,但是在大部分情況下已經夠用,而且使用std::unique_lock<std::mutex>會比較簡單,因為std::unique_lock<std::mutex>在聲明的時候就會初始化,在生命周期結束之後就會自動解鎖,是以我們不用太花精力來考慮什麼時候解鎖。我們來看看下面這段程式:

C++11 生産者消費者
C++11 生産者消費者

 運作結果:

C:\Windows\system32\cmd.exe /c producer_consumer.exe

producing 0

consuming 0

producing 1

consuming 1

producing 2

consuming 2

producing 3

consuming 3

producing 4

consuming 4

Hit any key to close this window...

更新:2012年8月4日16:53:25

make it simple, make it happen

繼續閱讀