三种C++生产者消费者启动方式
生产者和消费者是一种常见的并发编程模型,用于解决多线程环境下的数据共享和同步问题。在这个模型中,生产者负责生成数据并将其放入共享缓冲区,而消费者则负责从缓冲区中取出数据进行处理。
以下是生产者-消费者问题的基本描述:
-
生产者:
- 生产数据并将其放入共享缓冲区。
- 如果缓冲区已满,生产者应该等待直到有空间可用。
- 一旦将数据放入缓冲区,就通知消费者数据已经可用。
-
消费者:
- 从共享缓冲区中取出数据进行处理。
- 如果缓冲区为空,消费者应该等待直到有数据可用。
- 一旦取出数据,通知生产者有空间可用于继续生产。
+--+ +--+
| 生产者线程 | | 消费者线程 |
+--+ +--+
| |
| |
v v
生成数据项 取出数据项
| |
| |
v v
尝试放入缓冲区 尝试从缓冲区取出
| |
| |
v v
缓冲区已满,等待 缓冲区为空,等待
| |
| |
v v
放入缓冲区成功 取出数据项成功
| |
| |
v v
通知消费者线程 处理数据项
| |
| |
v v
... ...
第一种方式:普通函数实现生产者消费者线程
#include <iostream>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using namespace std::chrono_literals;
std::list<int> q;
std::mutex mtx;
std::condition_variable cond;
static void produce(int val) {
while(val--) {
std::unique_lock<std::mutex> guard(mtx);
q.push_back(val);
guard.unlock();
cond.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
static void consumer() {
int data = -1;
while(data != 0) {
std::unique_lock<std::mutex> guard(mtx);
while(q.empty())
cond.wait(guard);
data = q.front();
q.pop_front();
guard.unlock();
std::cout << data << std::endl;
}
}
void test() {
std::thread t1(produce,100);
std::thread t2(consumer);
t1.join();
t2.join();
}
int main() {
test();
return 0;
}
第二种方式:类内部启动启动生产者消费者线程
#include <iostream>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using namespace std::chrono_literals;
class Production{
public:
Production();
~Production();
static void produce(void *arg);
static void consumer(void *arg);
private:
std::thread th_pro;
std::thread th_con;
std::list<int> q;
std::mutex mtx;
std::condition_variable cond;
bool run_flag=true;
int val=100;
};
Production::Production(){
th_pro=std::thread(produce,this);
th_con=std::thread(consumer,this);
}
Production::~Production(){
run_flag=false;
th_pro.join();
th_con.join();
q.clear();
printf("~Production\n");
}
void Production::produce(void *arg){
Production *self=(Production*)arg;
while(self->run_flag){
std::unique_lock<std::mutex> guard(self->mtx);
self->q.push_back(self->val);
guard.unlock();
self->cond.notify_one();
self->val--;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void Production::consumer(void *arg){
Production *self=(Production*)arg;
while(self->run_flag){
//此种方式不需要使用while循环
std::unique_lock<std::mutex> guard(self->mtx);
if(!self->q.empty()){
int data = self->q.front();
self->q.pop_front();
guard.unlock();
std::cout << data << std::endl;
}
else{
auto now = std::chrono::system_clock::now();
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
self->cond.wait_until(guard,now+100ms);
std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
double duration_millsecond = std::chrono::duration<double, std::milli>(t2 - t1).count();
std::cout << (int)duration_millsecond << "ms" << std::endl;
guard.unlock();
}
}
}
void test() {
Production *a=new Production();
std::this_thread::sleep_for(20s);
delete a;
}
int main() {
test();
return 0;
}
第三种方式:类外部启动生产者消费者线程
#include <iostream>
#include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using namespace std::chrono_literals;
class Production{
public:
Production();
~Production();
void stop();
void produce();
void consumer();
private:
std::list<int> q;
std::mutex mtx;
std::condition_variable cond;
bool run_flag=true;
int val=100;
};
Production::Production(){
}
Production::~Production(){
q.clear();
printf("~Production\n");
}
void Production::stop(){
run_flag=false;
}
void Production::produce(){
while(run_flag){
std::unique_lock<std::mutex> guard(mtx);
q.push_back(val);
guard.unlock();
cond.notify_one();
val--;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void Production::consumer(){
while(run_flag){
//此种方式不需要使用while循环
std::unique_lock<std::mutex> guard(mtx);
if(!q.empty()){
int data = q.front();
q.pop_front();
guard.unlock();
std::cout << data << std::endl;
}
else{
auto now = std::chrono::system_clock::now();
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
cond.wait_until(guard,now+100ms);
std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
double duration_millsecond = std::chrono::duration<double, std::milli>(t2 - t1).count();
std::cout << (int)duration_millsecond << "ms" << std::endl;
guard.unlock();
}
}
}
void test() {
Production *a=new Production();
std::thread th_pro=std::thread(&Production::produce,a);
std::thread th_con=std::thread(&Production::consumer,a);
std::this_thread::sleep_for(20s);
a->stop();
th_pro.join();
th_con.join();
delete a;
}
int main() {
test();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库