天天看点

生产者消费者_生产者消费者问题项目实验

生产者-消费者问题描述

存在一个固定大小的缓冲区,两个(或以上)线程共享它,特别地,一个线程执行向该缓冲区写数据的任务即所谓的生产者,另一个线程执行从该缓冲区读数据的任务即所谓的消费者。因为是固定大小的缓冲区,所以也称为 有限缓冲问题

问题分析与解决方案

该问题涉及的对象包括缓冲区、生产者和消费者;

涉及的活动包括向缓冲区写数据、数据从缓冲区中移除;

问题的一个关键约束是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据;

问题的另一个关键特征是缓冲区既不满又不空时,保证生产和消费能同时进行,也就是说,当缓冲区为空时,消费者发送了消费请求会原地等待(进入睡眠),一旦生产了数据,消费者就会被唤醒,该数据就会立马被消费。同样地,当缓冲区为满时,生产者请求生产数据会原地等待(进入睡眠),一旦消费了数据,生产者就会被唤醒,该数据立马被存入。

采用pthreads线程、互斥锁机制来解决该问题,如下

首先,定义一个固定大小的缓冲区,其大小用宏BUFFER_SIZE表示,缓冲区条目可以自定义为一个类型,如下

typedef struct _buffer_item{  int value;  int id;}bufferItem_t;bufferItem_t buffer[BUFFER_SIZE];           

定义一个环形队列,操作上述的缓冲区数据,如下

typedef struct _queue{  bufferItem_t *buffer;  int head;  int tail;}queue_t;queue_t queueBuf;           

定义函数queue_en()实现向缓冲区写数据功能;定义函数queue_de()实现数据从缓冲区移除功能;其函数规格定义如下

int queue_en(queue_t *const p, bufferItem_t item){/*insert item into bufferreturn 1 if successful otherwisereturn 0 if buffer is fullreturn -1 indicating an error condition */}int queue_de(queue_t *const p, bufferItem_t *item){/* remove an object from bufferplace it in itemreturn 1 if successful otherwisereturn 0 if buffer is emptyreturn -1 indicating an error condition */}           

定义计数信号量sem_empty以记录缓冲区中有多少空的条目,初始化为BUFFER_SIZE;

定义计数信号量sem_full以记录buffer中有多少满的缓冲区,初始化为0;

定义互斥锁mutex以保护对缓冲区插入与删除的操作 ;

定义一个初始化函数buffer_init()实现以上初始化,该函数规格说明如下

void buffer_init(){  /*initialize the buffer  initialize the mutex  initialize the semophor  */}           

为每一个生产者创建一个单独线程,为每一个消费者创建一个单独线程。

假设有n个生产者为m个消费者提供服务,其中n,m通过命令行参数传入,同时,要求父进程创建了生产者和消费者线程后,睡眠一段时间,该时间长度也通过命令行参数传入,在此,可以定义主程序的规格说明如下

#include “buffer.h"int main(int argc, char *argv[]){ /*1.Get command line arguments argv[1],argv[2],argv[3]*/ /*2.initialization */ /*3.Create the producer thread(s)*/ /*4.Create the consumer thread(s)*/ /*5.Sleep*/ /*6.Exit*/}           

对于每一个生产者线程而言,它交替睡眠和向缓冲区插入一个随机数,通过同步机制自动控制该交替活动,即(如果缓冲区填满了则让该线程睡眠一下等待来一个消费者拿走一个数据)

void *producer(void *param) {  while(TRUE)  {    /*intert the item in the buffer if buffer is not full    or others dont operate the buffer */     /*sleep for a while */  }}           

对于每一个消费者线程而言,它交替睡眠和从缓冲区拿取一个数据,通过同步机制自动控制该交替活动,即(如果缓冲区已空了则让该线程再睡眠以下等待来一个生产者添加一个数据进来)

void *consumer(void *param) {  while(TRUE)  {    /*remove the item from the buffer if buffer is not full    or others dont operate the buff */     /*sleep for a while */  }}           

以下给出按照此方案编写的源代码。

解决方案的实施

请参考我的GitHub项目文件demo_boundedbuf.c          ,存储目录在 https://github.com/qinxiangke/UApiTest/tree/master/sync

测试

运行命令“./demo_boundedbuf 5000 2 8”,生产和消费活动可以无止境的执行下去,您可以尝试定义其他生产者-消费者组合

生产者消费者_生产者消费者问题项目实验

继续阅读