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)类,用于管理互斥锁的加锁和解锁,确保在发生异常或提前返回时,互斥锁能够被正确地释放,避免死锁和资源泄漏。然而,它们在功能和使用上有一些重要的区别。
- 灵活性:std::unique_lock提供了比std::lock_guard更多的灵活性。std::lock_guard在构造时锁定互斥量,在析构时自动解锁,没有提供手动解锁的功能,适用于需要在进入作用域时锁定互斥量,离开作用域时自动解锁的简单场景。而std::unique_lock则允许在需要时手动锁定和解锁互斥量,提供了更多的控制锁的行为,比如锁超时、不锁定等。
- 可移动性:std::lock_guard是不可移动的,即不能拷贝、赋值、移动,只能通过构造函数初始化和析构函数销毁。而std::unique_lock是可移动的,可以拷贝、赋值、移动,这增加了其使用的灵活性。
- 功能丰富性:std::unique_lock的功能更为丰富,它提供了更多的控制选项,比如可以设定超时时间尝试获取锁,或者尝试获取锁但不阻塞等。此外,std::unique_lock还可以与std::condition_variable一起使用,实现等待某个条件成立的操作。相比之下,std::lock_guard的功能较为简单,主要用于简单的锁定和解锁操作
浙公网安备 33010602011771号