上海十大网站排名,最成功的个人网站,鲜花加盟网站建设,wordpress做的著名网站文章目录 学习生产者消费者模型过程中要回答的两个问题生产者消费者模型的概念基于阻塞队列的生产者消费者模型编码实现Common.hLockGuard.hppCondtion.hppBlockQueue.hppTask.hppConProd.cc 学习生产者消费者模型过程中要回答的两个问题
1.条件变量是在条件满足的时候#x… 文章目录 学习生产者消费者模型过程中要回答的两个问题生产者消费者模型的概念基于阻塞队列的生产者消费者模型编码实现Common.hLockGuard.hppCondtion.hppBlockQueue.hppTask.hppConProd.cc 学习生产者消费者模型过程中要回答的两个问题
1.条件变量是在条件满足的时候会唤醒指定的线程----我们怎么知道条件是否满足呢 2.mutex的意义
生产者消费者模型的概念
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产 者和消费者彼此之间不直接通讯而通过阻塞队列来进行通讯所以生产者生产完数据之后不用等待消费者处理直接扔给阻塞队列消费者不找生产者要数据而是直接从阻塞队列里取阻塞队列就相当于一个缓冲区平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。
生产者消费者模型 生产者消费者模型优点 解耦 支持并发 支持忙闲不均
上面的优点全都是因为有一个仓库的存在。 生产者消费者模型类比 消费者去超市买商品。 厂家往超市放商品 而这就是生产者消费者模型它的核心意义是提高了效率并且通过超市让消费者和厂家进行了解耦合的关系不用让消费者和厂家进行沟通。
超市本质就是一个商品缓冲区。
生产者消费者模型有 2种角色生产者和消费者 1种交易场所超市 3中关系 生产者和生产者-----竞争且互斥 消费者和消费者----竞争且互斥 生产者和消费者----互斥且同步
消费者和生产者由线程承担----给线程进行角色化 超市某种数据结构—表示缓冲区 商品数据
生产者生产的数据是从哪里来的 消费者如何使用发送过来的数据 而在现实生活中生产数据和发送数据的过程都需要花时间。
1.条件变量是在条件满足的时候会唤醒指定的线程----我们怎么知道条件是否满足呢消费者和生产者各自知道。 超市没有商品了消费者知道。因为消费者去超市买不到商品 超市商品满了生产者知道因为生产者刚想超市放了一堆商品 2.mutex的意义 保护临界资源
基于阻塞队列的生产者消费者模型
BlockingQueue 在多线程编程中阻塞队列(Blocking Queue)是一种常用于实现生产者和消费者模型的数据结构。其与普通的队列区别在于当队列为空时从队列获取元素的操作将会被阻塞直到队列中被放入了元素当队列满时往队列里存放元素的操作也会被阻塞直到有元素被从队列中取出(以上的操作都是基于不同的线程来说的线程在对阻塞队列进程操作时会被阻塞)
编码实现
Common.h
#pragma once
#include iostream
#include pthread.h
#include queue
#include unistd.h
#include ctime
#include functional#define gDefaultCap 5//阻塞队列默认的数据个数
#define CTNUM 1//消费者线程个数
#define PTNUM 1//生产者线程个数LockGuard.hpp
//自己封装的锁定义后会自动初始化和销毁
#pragma once
#include Common.hclass Mutex
{
public:Mutex(){pthread_mutex_init(_mtx,nullptr);}pthread_mutex_t GetMutex(){return _mtx;}~Mutex(){pthread_mutex_destroy(_mtx);}
private:pthread_mutex_t _mtx;
};//RAII风格会自动加锁和解锁
class LockGuard
{
public:LockGuard(Mutex* mtx):_mtx(mtx){pthread_mutex_lock(_mtx-GetMutex());//std::cout lock std::endl;}~LockGuard(){pthread_mutex_unlock(_mtx-GetMutex());//std::cout unlock std::endl;}
private:Mutex* _mtx;
};Condtion.hpp
#include Common.h
//自己封装的条件变量定义后会自动初始化和销毁
class Condtion
{
public:Condtion(){pthread_cond_init(_cond,nullptr);}pthread_cond_t GetCond(){return _cond;}~Condtion(){pthread_cond_destroy(_cond);}
private:pthread_cond_t _cond;
};BlockQueue.hpp
#pragma once
#include Common.h
#include LockGuard.hpp
#include Condtion.hpptemplateclass T
class BlockQueue
{
private:bool Empty(){return bq.size() 0;}bool Full(){return bq.size() _capacity;}
public:BlockQueue(int capacity gDefaultCap):_capacity(capacity){}void Push(T in){//RAII风格加锁会自动解锁LockGuard lockgrard(_mtx);//条件不满足就一直等待while(Full()){pthread_cond_wait(_FullCond.GetCond(),_mtx.GetMutex());}bq.push(in);//唤醒消费者线程pthread_cond_signal(_EmptyCond.GetCond());}void Pop(T* out){//RAII风格加锁会自动解锁LockGuard lockgrard(_mtx);//条件不满足就一直等待while(Empty()){pthread_cond_wait(_EmptyCond.GetCond(),_mtx.GetMutex());}*out bq.front();bq.pop();//唤醒生产者线程pthread_cond_signal(_FullCond.GetCond());}~BlockQueue(){}
private:std::queueT bq;//阻塞队列int _capacity;//阻塞队列的最大容量Mutex _mtx;//自己封装的锁会自动初始化和销毁Condtion _EmptyCond;//自己封装的条件变量会自动初始化和销毁Condtion _FullCond;//自己封装的条件变量会自动初始化和销毁
};Task.hpp
#pragma once
#include Common.htypedef std::functionint(int, int) func_t;class Task
{
public:Task(){}Task(int x, int y, func_t func): _x(x),_y(y),_func(func){}//仿函数int operator()(){return _func(_x, _y);}public:int _x;int _y;func_t _func;
};ConProd.cc
#include Common.h
#include BlockQueue.hpp
#include Task.hppint myAdd(int x,int y)
{return xy;
}void* ConsumerRoutine(void* args)
{BlockQueueTask* bq (BlockQueueTask*)args;Task t;while(true){//获取一个任务bq-Pop(t);std::cout [ pthread_self() ] 获取一个任务: t._x t._y t() std::endl;sleep(1);}
}
void* ProducterRoutine(void* args)
{BlockQueueTask* bq (BlockQueueTask*)args;while(true){//制作一个任务int x rand() % 100 1;int y rand()%30 1;Task t(x,y,myAdd);std::cout [ pthread_self() ] 制作一个任务: x y ? std::endl;bq-Push(t);sleep(1);}
}
int main()
{srand((unsigned int)time(nullptr) ^ getpid() ^ 0X3333);//定义消费者线程和生成者线程的id数组pthread_t Consumer[CTNUM];pthread_t Producter[PTNUM];//创建阻塞队列BlockQueueTask* bqueue new BlockQueueTask;//创建消费者线程for(int i 0; i CTNUM; i){pthread_create(Consumer i,nullptr,ConsumerRoutine,(void*)bqueue);}//创建生产者线程for(int i 0; i PTNUM; i){pthread_create(Producter i,nullptr,ProducterRoutine,(void*)bqueue);}//等待消费者线程for(int i 0; i CTNUM; i){pthread_join(Consumer[i],nullptr);}//等待生产者线程for(int i 0; i CTNUM; i){pthread_join(Producter[i],nullptr);}return 0;
}