班级姓名:学号:成绩:实验名称: 生产者和消费者问题1.实验目的:“生产者消费者”问题是一个著名的同时性编程问题的集合。
通过编写经典的“生产者消费者”问题的实验,读者可以进一步熟悉Linux 中多线程编程,并且掌握用信号量处理线程间的同步互斥问题。
2.实验内容:“生产者消费者”问题描述如下。
有一个有限缓冲区和两个线程:生产者和消费者。
他们分别把产品放入缓冲区和从缓冲区中拿走产品。
当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。
它们之间的关系如下图所示:这里要求用有名管道来模拟有限缓冲区,用信号量来解决生产者消费者问题中的同步和互斥问题。
3.实验方法:(1)使用信号量解决(2)思考使用条件变量解决4.实验过程(1)信号量的考虑这里使用3个信号量,其中两个信号量avail和full分别用于解决生产者和消费者线程之间的同步问题,mutex是用于这两个线程之间的互斥问题。
其中avail初始化为N(有界缓冲区的空单元数),mutex 初始化为1,full初始化为0。
/**/#include <>#include <>#include <>#include <>#include <>#include <sys/>#include <>#include <>#define FIFO "myfifo"#define N 5int lock_var;time_t end_time;char buf_r[100];sem_t mutex,full,avail;int fd;void pthread1(void *arg);void pthread2(void *arg);int main(int argc, char *argv[]){pthread_t id1,id2;pthread_t mon_th_id;int ret;end_time = time(NULL)+30;/*创建有名管道*/if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST)) printf("cannot create fifoserver\n");printf("Preparing for reading bytes...\n");memset(buf_r,0,sizeof(buf_r));/*打开管道*/fd=open(FIFO,O_RDWR|O_NONBLOCK,0);if(fd==-1){perror("open");exit(1);}/*初始化互斥信号量为1*/ret=sem_init(&mutex,0,1);/*初始化avail信号量为N*/ret=sem_init(&avail,0,N);/*初始化full信号量为0*/ret=sem_init(&full,0,0);if(ret!=0){perror("sem_init");}/*创建两个线程*/ret=pthread_create(&id1,NULL,(void *)productor, NULL); if(ret!=0)perror("pthread cread1");ret=pthread_create(&id2,NULL,(void *)consumer, NULL); if(ret!=0)perror("pthread cread2");pthread_join(id1,NULL);pthread_join(id2,NULL);exit(0);}/*生产者线程*/void productor(void *arg){int i,nwrite;while(time(NULL) < end_time){/*P操作信号量avail和mutex*/sem_wait(&avail);sem_wait(&mutex);/*生产者写入数据*/if((nwrite=write(fd,"hello",5))==-1){if(errno==EAGAIN)printf("The FIFO has not been read try later\n"); }elseprintf("write hello to the FIFO\n");/*V操作信号量full和mutex*/sem_post(&full);sem_post(&mutex);sleep(1);}}/*消费者线程*/void consumer(void *arg){int nolock=0;int ret,nread;while(time(NULL) < end_time){/*P操作信号量full和mutex*/sem_wait(&full);sem_wait(&mutex);memset(buf_r,0,sizeof(buf_r));if((nread=read(fd,buf_r,100))==-1){if(errno==EAGAIN)printf("no data yet\n");}printf("read %s from FIFO\n",buf_r);/*V操作信号量avail和mutex*/sem_post(&avail);sem_post(&mutex);sleep(1);}}(2)条件变量的考虑#include <>#include <>#define BUFFER_SIZE 4#define OVER (-1)struct producers//定义生产者条件变量结构{int buffer[BUFFER_SIZE];pthread_mutex_t lock;int readpos, writepos;pthread_cond_t notempty;pthread_cond_t notfull;};//初始化缓冲区void init(struct producers *b){pthread_mutex_init(&b->lock,NULL);pthread_cond_init(&b->notempty,NULL);pthread_cond_init(&b->notfull,NULL);b->readpos=0;b->writepos=0;}//在缓冲区存放一个整数void put(struct producers *b, int data){pthread_mutex_lock(&b->lock);//当缓冲区为满时等待while((b->writepos+1)%BUFFER_SIZE==b->readpos) {pthread_cond_wait(&b->notfull,&b->lock);}b->buffer[b->writepos]=data;b->writepos++;if(b->writepos>=BUFFER_SIZE) b->writepos=0; //发送当前缓冲区中有数据的信号pthread_cond_signal(&b->notempty);pthread_mutex_unlock(&b->lock);}int get(struct producers *b){int data;pthread_mutex_lock(&b->lock);while(b->writepos==b->readpos){pthread_cond_wait(&b->notempty,&b->lock); }data=b->buffer[b->readpos];b->readpos++;if(b->readpos>=BUFFER_SIZE) b->readpos=0; pthread_cond_signal(&b->notfull);pthread_mutex_unlock(&b->lock);return data;}struct producers buffer;void *producer(void *data){int n;for(n=0;n<10;n++){printf("Producer : %d-->\n",n);put(&buffer,n);}put(&buffer,OVER);return NULL;}void *consumer(void *data){int d;while(1){d=get(&buffer);if(d==OVER) break;printf("Consumer: --> %d\n",d);}return NULL;}int main(){pthread_t tha,thb;void *retval;init(&buffer);pthread_create(&tha,NULL,producer,0); pthread_create(&thb,NULL,consumer,0);pthread_join(tha,&retval); pthread_join(thb,&retval); return 0;}。