下面是一個生産者消費者問題,來介紹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鍵之後停止)
運作結果:
對程式進行一下說明,程式中有三個線程,主線程、生産者線程、消費者線程,三個線程之間亂序執行,通過一些全局變量來控制他們的執行順序。主線程的作用是控制生産消費過程是否結束,當程式運作之後,主線程通過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:\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