C++ 生产者消费者条件变量

#include <iostream>  
#include <vector>  
#include <queue>  
#include <mutex>  
#include <condition_variable>  
#include <thread>  

using namespace std;  
  
struct data_chunk {
    int count;  
};  
  
std::mutex mut;  
std::queue<data_chunk> data_queue;  
std::condition_variable data_cond;  
int count = 10000;  
bool finished_producing = false;  
  
void data_product_thread() {  
    while(count--){  
        std::lock_guard<std::mutex> lk(mut);  
        data_chunk data = {count};  
        data_queue.push(data);  
        data_cond.notify_one();  
    }
    {  
        std::lock_guard<std::mutex> lk(mut);  
        finished_producing = true;  
    }  
    data_cond.notify_all(); // Notify all consumers that we're done  
}  
  
void data_consum_thread() {  
    while(true) {  
        std::unique_lock<std::mutex> lk(mut);  
        data_cond.wait(lk,[]{return !data_queue.empty()||finished_producing;});
        if(finished_producing&&data_queue.empty()){
            break;
        }
        data_chunk data = data_queue.front();  
        data_queue.pop();  
        cout << data.count << endl;
    }  
}  
  
int main() {  
    std::thread t1(data_product_thread);  
    std::vector<std::thread> consums;  
    for(int i = 0; i < 10; ++i) { 
        consums.push_back(std::thread(data_consum_thread));  
    }  
    for(auto& consum : consums) {  
        consum.join();  
    }  
    t1.join();  
    return 0;  
}

std::condition_variable 的 wait 函数需要能够在等待条件时释放锁,并在条件满足时重新获取锁。

std::lock_guard和std::unique_lock都是C++标准库提供的RAII(Resource Acquisition Is Initialization)类,用于管理互斥锁的加锁和解锁,确保在发生异常或提前返回时,互斥锁能够被正确地释放,避免死锁和资源泄漏。然而,它们在功能和使用上有一些重要的区别。

  1. 灵活性:std::unique_lock提供了比std::lock_guard更多的灵活性。std::lock_guard在构造时锁定互斥量,在析构时自动解锁,没有提供手动解锁的功能,适用于需要在进入作用域时锁定互斥量,离开作用域时自动解锁的简单场景。而std::unique_lock则允许在需要时手动锁定和解锁互斥量,提供了更多的控制锁的行为,比如锁超时、不锁定等。
  2. 可移动性:std::lock_guard是不可移动的,即不能拷贝、赋值、移动,只能通过构造函数初始化和析构函数销毁。而std::unique_lock是可移动的,可以拷贝、赋值、移动,这增加了其使用的灵活性。
  3. 功能丰富性:std::unique_lock的功能更为丰富,它提供了更多的控制选项,比如可以设定超时时间尝试获取锁,或者尝试获取锁但不阻塞等。此外,std::unique_lock还可以与std::condition_variable一起使用,实现等待某个条件成立的操作。相比之下,std::lock_guard的功能较为简单,主要用于简单的锁定和解锁操作
posted @ 2024-03-28 17:04  fchy822  阅读(29)  评论(0)    收藏  举报