三种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;
}

posted @   BreakingY  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示