一、实验目的及要求
“生产者消费者”问题是一个著名的同时性编程问题的集合。通过编写经典的”生产者消费者”问题的实验,读者可以进一步熟悉 Linux 中多线程编程,并且掌握用信号量处理线程间的同步互斥问题。
二、实验仪器设备与软件环境
VMware Workstation Pro
三、实验过程及实验结果分析
“生产者消费者”问题描述如下。 有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中 拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。 它们之间的关系如下图所示:
这里要求用有名管道来模拟有限缓冲区,用信号量来解决生产者消费者问题中的同步和互斥问题。
(1) 使用信号量解决
实验结果:
实验代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/stat.h>
#define MYFIFO "myfifo"
#define BUFFER_SIZE 3
#define UNIT_SIZE 6
#define RUN_TIME 30
#define DELAY_TIME_LEVELS 5.0
int fd;
time_t end_time;
sem_t mutex,full,avail;
void *producer(void *arg)
{
int real_write;
int delay_time=0;
while(time(NULL)<end_time)
{
delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX)/2.0)+1;
sleep(delay_time);
sem_wait(&avail);
sem_wait(&mutex);
printf("\nProducer:delay=%d\n",delay_time);
if((real_write=write(fd,"hello",UNIT_SIZE))==-1)
{
if(errno==EAGAIN)
{
printf("The FIFO has not been read yet.Please try later\n");
}
}
else
{
printf("Write %d to the FIFO\n",real_write);
}
sem_post(&full);
sem_post(&mutex);
}
pthread_exit(NULL);
}
void *customer(void *arg)
{
unsigned char read_buffer[UNIT_SIZE];
int real_read;
int delay_time;
while(time(NULL)<end_time)
{
delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX))+1;
sleep(delay_time);
sem_wait(&full);
sem_wait(&mutex);
memset(read_buffer,0,UNIT_SIZE);
printf("\nCustomer:delay=%d\n",delay_time);
if((real_read=read(fd,read_buffer,UNIT_SIZE))==-1)
{
if(errno==EAGAIN)
{
printf("No data yet\n");
}
}
printf("Read %s from FIFO\n",read_buffer);
sem_post(&avail);
sem_post(&mutex);
}
pthread_exit(NULL);
}
int main()
{
pthread_t thrd_pro_id,thrd_cus_id;
pthread_t mon_th_id;
int ret;
srand(time(NULL));
end_time=time(NULL)+RUN_TIME;
if((mkfifo(MYFIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
{
printf("Cannot create fifo\n");
return errno;
}
fd=open(MYFIFO,O_RDWR,0666);
if(fd==-1)
{
printf("Open fifo error\n");
return fd;
}
ret=sem_init(&mutex,0,1);
ret+=sem_init(&avail,0,BUFFER_SIZE);
ret+=sem_init(&full,0,0);
if(ret!=0)
{
printf("Any semaphore initialization failed\n");
return ret;
}
ret=pthread_create(&thrd_pro_id,NULL,producer,NULL);
if(ret!=0)
{
printf("Create producer thread error\n");
return ret;
}
ret=pthread_create(&thrd_cus_id,NULL,customer,NULL);
if(ret!=0)
{
printf("Create producer thread error\n");
return ret;
}
pthread_join(thrd_pro_id,NULL);
pthread_join(thrd_cus_id,NULL);
close(fd);
return 0;
}
(2)思考使用条件变量解决
实验结果:
实验代码:
#include <stdio.h>
#include <pthread.h>
#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;
}
特别注意:如果运行时出现这种情况:
说明此时你并没有权限,上个权限就好了(sudo -s)
【上知乎搜:乘风与你渡晚舟】
csdn网站与知乎网站同作者
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)