c++11 多線程生產者消費者模型

一段簡單的示例代碼

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
int i = 0;
std::mutex mtx;
std::condition_variable condition_in, condition_out;
void in(int id)
{
    while (true)
    {
        //(1)
        std::unique_lock<std::mutex> in(mtx);
        condition_in.wait(in, [id](){
            std::cout << "condition_in.wait id:" << id << std::endl;
            return i < 5; 
        });
        std::cout << "thread id:"<<id<<"# "<<"===>"<<++i<<std::endl;
        //(2)
        condition_out.notify_one();
        //(3)
    }
}
void out(int id)
{
    while (true)
    {
        std::unique_lock<std::mutex> in(mtx);
        condition_out.wait(in, [id](){
            std::cout << "condition_out.wait id: " << id <<std::endl;
            return i > 1;
        });
        i -= 2;
        std::cout << "thread id:" << id<<"# "<<"===>" <<i << std::endl;
        condition_in.notify_one();
    }
}
void main()
{
    std::thread t1(in,0);
    std::thread t2(out,1);
    //std::thread t3(out,2);
    //std::thread t4(out,3);
    //std::thread t5(out,4);

    t1.join();
}

std::unique_lock

std::unique_lock 是一個使用RAII機制來管理 std::mutex 的一個類,相比于 std::lock_guard 有更靈活的方式,但會比 std::lock_guard 使用更多的空間。

Member functions

Locking/unlocking

lock
try_lock
try_lock_for
try_lock_until
unlock

Modifiers

operator= (Move-assign unique_lock)
swap
release

Observers

owns_lock
operator bool (Return whether it owns a lock)
mutex

運行結果

單消費者單生產者

condition_in.wait id:0
thread id:0# ===>1
condition_out.wait id: 1
condition_in.wait id:0
thread id:0# ===>2
condition_in.wait id:0
thread id:0# ===>3
condition_out.wait id: 1
thread id:1# ===>1
condition_in.wait id:0
thread id:0# ===>2
condition_out.wait id: 1
thread id:1# ===>0
condition_in.wait id:0
thread id:0# ===>1
condition_out.wait id: 1
condition_in.wait id:0
thread id:0# ===>2
condition_in.wait id:0
thread id:0# ===>3
condition_out.wait id: 1
thread id:1# ===>1
condition_in.wait id:0
thread id:0# ===>2
condition_out.wait id: 1
thread id:1# ===>0

結果大致如預期,但是通過觀察發現產品的個數總是以0->1->2->3->1->2->0的規律變化,按理說每次產品增加到2之后喚醒消費者線程應該就會將2個產品取走了。通過分析輸出日志,應該是因為被condition阻塞的線程從喚醒到重新上鎖的時間要長于 std::unique_lock<std::mutex> 鎖爭用時直接上鎖的時間。另外,啟動消費者和生產者線程的先后順序也會影響剛開始的輸出序列,但整體的變化規律不會變。在(1)處插入

if(i > 1)

然后先啟動t2,再啟動t1線程,仍然可以觀察到相同序列,基本證明猜想正確。
多消費者多生產者的情況也完全符合預期。不過經過一番嘗試,并沒有模擬出虛假喚醒的情況,有待進一步考察。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容