生产者和消费者问题

更新时间:2023-11-01 08:20:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

班级 姓名: 学号: 成绩:

实验名称: 生产者和消费者问题

1.实验目的:

“生产者消费者”问题是一个著名的同时性编程问题的集合。通过编写经典的“生产者消费者”问题的实验,读者可以进一步熟悉Linux 中多线程编程,并且掌握用信号量处理线程间的同步互斥问题。

2.实验内容:

“生产者消费者”问题描述如下。 有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。它们之间的关系如下图所示:

这里要求用有名管道来模拟有限缓冲区,用信号量来解决生产者消费者问题中的同步和互斥问题。

3.实验方法:

(1)使用信号量解决

(2)思考使用条件变量解决

4.实验过程

(1)信号量的考虑 这里使用3个信号量,其中两个信号量avail和full分别用于解决生产者和消费者线程之间的同步问题,mutex是用于这两个线程之间的互斥问题。其中avail初始化为N(有界缓冲区的空单元数),mutex 初始化为1,full初始化为0。

/*product.c*/ #include #include #include #include #include #include #include #include

#define FIFO \#define N 5 int 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(\printf(\memset(buf_r,0,sizeof(buf_r));

/*打开管道*/

fd=open(FIFO,O_RDWR|O_NONBLOCK,0); if(fd==-1) {

perror(\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(\}

/*创建两个线程*/

ret=pthread_create(&id1,NULL,(void *)productor, NULL); if(ret!=0)

perror(\

ret=pthread_create(&id2,NULL,(void *)consumer, NULL); if(ret!=0)

perror(\

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,\) {

if(errno==EAGAIN)

printf(\} else

printf(\/*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(\}

printf(\/*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(\ put(&buffer,n); }

put(&buffer,OVER); return NULL; }

void *consumer(void *data) { int d; while(1) {

d=get(&buffer); if(d==OVER) break;

printf(\ }

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

本文来源:https://www.bwwdw.com/article/qs22.html

Top