生产者-消费者模型

首先了解两个概念:1. promise和future      2. 条件变量

Promise和Future:

promise对象就是一个任务,有人(线程)去接这项任务并且承诺未来某一时刻会完成这项任务并做一个回馈,而future就是任务发起者用来接收promise完成结果的东西。

 

条件变量:

1. 条件变量的使用场景:

头文件#include<condition_variable>

2. 条件变量使用流程图例:

以下图为例:主线程是小红做作业,t0线程是小红妈妈给他买麦当劳(买麦当劳这一动作定义为func函数)。但只有当妈妈达到了一定的满意状态才会给买,cv就是这个过程中定义的条件变量,流程为:

1. 小红做作业做到十点,询问了一次妈妈(cv.notify_one()),妈妈表示不满意,才做了这么一会就想吃麦当劳,给了一巴掌。

2. 小红继续做作业到下午一点,妈妈还是不满意,如上。

3. 终于小红做到半夜十一点,妈妈终于满意,执行了t0线程的func,买了麦当劳。

这期间cv.wait(lock,[&](){满意状态})就是妈妈的情绪是否到达阈值状态的一个询问,满意了才会执行t0线程的相关的相关动作。

然后进行生产者——消费者模型的介绍

生产者——消费者模型:

生产者消费者问题是一个经典的多线程同步问题。该问题描述了两个进程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是不断的生成数据,而与此同时,消费者则不断消耗这些数据。该问题的关键就是要保证当生产者生产了产品后,若消费者还没有消费此产品,则生产者停止生产并等待,直到消费者消费了此产品;当消费者消费了产品后,若生产者还没有及时生产新的产品,则消费者停止消费并等待,直到生产者生产了新产品。

#include<thread>
#include<queue>
#include<mutex>//锁
#include<string>
#include<stdio.h>
#include<chrono>
#include<condition_variable>
#include<memory>
#include<future>
using namespace std;


//贡献资源访问问题
//queue, stl对象不是线程安全,需要用锁


//如果生产速度大于消费速度,会产生堆积,需要设置溢出限制
//即队列满了,不生产,等待队列有空间在生产
//push之前对队列进行判断,通过条件变量实现

struct Job{
    shared_ptr<promise<string>> pro;
    string input;
};


queue<Job> qjobs_;
mutex lock_;
condition_variable cv_;
const int limit = 5;

//生产者
void video_capture(){
    int pic_id=0;
    while(true){
        Job job;
        {
            //生产加锁,作用范围不包括等待
            unique_lock<mutex> l(lock_);
            char name[100];
            sprintf(name,"PIC-%d",pic_id++);
            printf("生产了新图片:%s, qjobs_.size= %d\n",name, qjobs_.size());


            //一旦进入wait则解锁,一旦退出wait则加锁
            cv_.wait(l,[&](){
                //return false, 则继续等待
                //return true,则不等待,跳出wait
                return qjobs_.size() < limit;
            });


            //消费者有多个,对应到应用场景中可能是多个模型(检测、分割等等),分发数据到不同模型中异步进行在同一回收增大效率,需要从消费者中拿回数据
            
            job.pro.reset(new promise<string>());
            job.input = name;
            qjobs_.push(job);


            //拿消费者返回的结果
            //.get过后实现等待,等待消费者执行set_value,拿到结果



        }
        auto result = job.pro->get_future().get();
        printf("pic %s -> %s",job.input.c_str(),result.c_str());

        this_thread::sleep_for(chrono::milliseconds(500));
    }
}

//消费者
void infer_worker(){
    while(true){
        if(!qjobs_.empty()){
            {
                unique_lock<mutex> l(lock_);//消费加锁,作用不包含等待,等待的过程就是另一线程填充和消费的时候,此时线程安全
                auto pic = qjobs_.front();
                qjobs_.pop();

                //每消费一个就通知cv_判断
                cv_.notify_one();

                printf("消费了图片:%s\n",pic.input.c_str());

                //对应处理过程
                auto new_pic = pic.input+"---infer";
                //返回生产者
                pic.pro->set_value(new_pic);
            }

            this_thread::sleep_for(chrono::milliseconds(1000));
        }
        //不执行代码时交出控制权
        this_thread::yield();
    }
}

int main(){
    thread t0(video_capture);
    thread t1(infer_worker);


    t0.join();
    t1.join();


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值