Linux实验 ---- 生产者和消费者问题 实验四

实验目的

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

实验内容

“生产者消费者”问题描述如下。
有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。它们之间的关系如下图所示:
这里要求用有名管道来模拟有限缓冲区,用信号量来解决生产者消费者问题中的同步和互斥问题。

实验步骤

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

实验过程

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

/*product.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <fcntl.h>
#define FIFO "myfifo"
#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("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);
(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; 
}

实验结果

在这里插入图片描述

六 总结

与fork不同的是pthread_ create创建的线程不与父线程在同一点开始运行,而是从指定的函.数开始运行, 该函数运行完后,该线程也就退了。
线程依赖进程存在的,如果创建线程的进程结束了,线程也就结了。.
线程函数的程序在pthread库中,故链接时要加上参数lpthread.
gcc pthread_ _test.c -0 pthread test -Ipthread
掌握线程的基本操作,了解函数的基本操作。

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个基于Linux生产者消费者问题实验步骤: 1. 编写代码:首先,需要编一个程序来模拟生产者消费者问题。可以使用C或C++编程语言,使用POSIX线程库或pthread库来实现多线程。 2. 定义缓冲区:在程序中定义一个缓冲区,用于存储产品。可以使用数组或链表等数据结构来实现缓冲区。 3. 定义互斥锁和条件变量:在程序中定义一个互斥锁和两个条件变量,用于同步线程之间的操作。互斥锁用于保护缓冲区,条件变量用于通知线程何时读取或写入缓冲区。 4. 创建线程:在程序中创建两个线程:一个线程作为生产者,另一个线程作为消费者。 5. 实现生产者线程:在生产者线程中,使用互斥锁和条件变量来保护缓冲区,生成产品并将其放入缓冲区。 6. 实现消费者线程:在消费者线程中,使用互斥锁和条件变量来保护缓冲区,从缓冲区中取出产品并消费它。 7. 编译代码:使用gcc或g++编译器来编译代码,并生成可执行文件。 8. 运行程序:在命令行中运行可执行文件,观察程序的输出结果,以确保它能够正确地模拟生产者消费者问题。 需要注意的是,生产者消费者问题是一个经典的同步问题,实现起来并不容易。在编写代码之前,需要先理解问题的本质,并选择合适的同步机制来解决它。同时,还需要仔细设计程序,以确保它能够正确地同步线程之间的操作,避免出现死锁或竞争条件等问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值