Linux第六个实验报告

一木 712 views 0

实验六 生产者和消费者问题

实验目标

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

实验内容:

“生产者消费者”问题描述如下。

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

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

知识点回顾

  • 信号量
  • 线程

3.实验步骤:

(1)使用信号量解决

用到了三个信号量  empty_sem  full_sem  mutex

sem_t empty_sem; // 同步信号量,当没产品时阻止消费者消费

sem_t full_sem;  // 同步信号量,当满了时阻止生产者放产品

pthread_mutex_t mutex; // 互斥信号量,一次只有一个线程访问缓冲

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

 

(3)编码过程

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <pthread.h>

#include <semaphore.h>

#include <signal.h>

 

#define N 5   // 消费者或者生产者的数目

#define M 10 // 缓冲数目

 

int in = 0; // 生产者放置产品的位置

int out = 0; // 消费者取产品的位置

 

int buff[M] = { 0 }; // 缓冲初始化为0,开始时没有产品

 

sem_t empty_sem; // 同步信号量,当没产品时阻止消费者消费

sem_t full_sem;  // 同步信号量,当满了时阻止生产者放产品

pthread_mutex_t mutex; // 互斥信号量,一次只有一个线程访问缓冲

 

int product_id = 0; //生产者id

int prochase_id = 0; //消费者id

//信号处理函数

void Handlesignal(int signo)

{

printf("程序退出\n",signo);

exit(0);

}

/* 打印缓冲情况 */

void print() {

int i;

printf("产品队列为:\n");

for(i = 0; i < M; i++)

printf("%d  ", buff[i]);

printf("\n");

}

 

/* 生产者方法 */

void *product() {

int  id = ++product_id;

while(1)

{//重复进行

//用sleep的数量可以调节生产和消费的速度,便于观察

sleep(2);

sem_wait(&empty_sem);

pthread_mutex_lock(&mutex);

printf("Product id :%d\n", id);

in= (in % M)+1;

printf("生产者%d在产品队列中放入第%d个产品:\n", id, in);

in--;

buff[in]= 1;

print();

++in;

pthread_mutex_unlock(&mutex);

sem_post(&full_sem);

}

}

/* 消费者方法 */

void *prochase() {

int id = prochase_id;

while(1)

{//重复进行

//用sleep的数量可以调节生产和消费的速度,便于观察

sleep(3);

sem_wait(&full_sem);

pthread_mutex_lock(&mutex);

printf("Prochase id:%d\n", id);

out= (out % M)+1;

printf("消费者%d从产品队列中取出第%d个产品\n", id, out);

out--;

buff[out]= 0;

print();

++out;

pthread_mutex_unlock(&mutex);

sem_post(&empty_sem);

}

}

 

int main() {

printf("生产者和消费者数目都为5,产品缓冲为10,生产者每2秒生产一个产品,\n消费者每3秒消费一个产品,Ctrl+c退出程序\n");

pthread_t id1[N];

pthread_t id2[N];

int i;

int ret[N];

//结束程序

if(signal(SIGINT,Handlesignal)==SIG_ERR)

{

//按ctrl+C产生SIGINT信号

printf("信号安装出错\n");

}

// 初始化同步信号量

int ini1 = sem_init(&empty_sem, 0, M);//产品队列缓冲同步

int ini2 = sem_init(&full_sem, 0, 0);//线程运行同步

if(ini1 && ini2 != 0)

{

printf("信号量初始化失败!\n");

exit(1);

}

//初始化互斥信号量

int ini3 = pthread_mutex_init(&mutex, NULL);

if(ini3 != 0)

{

printf("线程同步初始化失败!\n");

exit(1);

}

// 创建N个生产者线程

for(i = 0; i < N; i++) {

ret[i]= pthread_create(&id1[i], NULL, product, (void *) (&i));

if(ret[i] != 0) {

printf("生产者%d线程创建失败!\n", i);

exit(1);

}

}

//创建N个消费者线程

for(i = 0; i < N; i++)

{

ret[i]= pthread_create(&id2[i], NULL, prochase, (void *)(&i));

if(ret[i] != 0)

{

printf("消费者%d线程创建失败!\n", i);

exit(1);

}

}

//等待线程销毁

for(i = 0; i < N; i++) {

pthread_join(id1[i], NULL);

pthread_join(id2[i],NULL);

}

exit(0);

}

 

 

实验报告

链接:https://pan.baidu.com/s/1kiKVX9mxdGtEVNw23Mn8mw
提取码:kk1v
复制这段内容后打开百度网盘手机App,操作更方便哦

 

 

实验现象

 

发表评论 取消回复
表情 图片 链接 代码

分享