当前位置:文档之家› 实验四 同步与互斥 Linux实验报告

实验四 同步与互斥 Linux实验报告

实验四同步与互斥【实验目的和要求】1、掌握进程(线程)的同步与互斥。

2、掌握生产者消费者问题的实现方法。

3、掌握多线程编程方法。

【实验内容】实现生产者消费者问题1、有一个仓库,生产者负责生产产品,并放入仓库,消费者会从仓库中拿走产品(消费)。

2、仓库中每次只能入一个(生产者或消费者)。

3、仓库中可存放产品的数量最多10个,当仓库放满时,生产者不能再放入产品。

4、当仓库空时,消费者不能从中取出产品。

5、生产、消费速度不同。

【实验原理】1、信号量mutex提供对缓冲池访问的互斥要求并初始化为1,信号量empty和full分别用来表示空缓冲项和满缓冲项的个数,信号量empty初始化为n,信号量full初始化为0。

2、定义如下结构及数据:定义缓冲区内的数据类型:typedef int buffer_item;缓冲区:buffer_item buffer[BUFFER_SIZE];对缓冲区操作的变量:int in,out;信号量mutex提供了对缓冲池访问的互斥要求:pthread_mutex_t mutex;信号量empty和full分别表示空缓冲顶和满缓冲顶的个数:sem_t empty,full;可以设定生产者的生产速度及消费者的消费速度:int pro_speed,con_speed;对缓冲区操作的自增函数:#define inc(k)if(k<BUFFER_SIZE)k=k+1;else k=03、并定义了如下实现问题的函数模块:将生产的产品放入缓冲区:int insert_item(buffer_item item)从缓冲区内移走一个产品:int remove_item(buffer_item*item)生产者进程:void*producer(void*param)消费者进程:void*consumer(void*param)生产者结构进程消费者结构进程【程序代码】//sx.c#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<semaphore.h>#include<time.h>#define inc(k) if(k<BUFFER_SIZE) k=k+1;else k=0#define BUFFER_SIZE 10//缓冲区的大小typedef int buffer_item;//定义缓冲区内的数据类型buffer_item buffer[BUFFER_SIZE];//缓冲区int in,out;//对缓冲区操作的变量pthread_mutex_t mutex;//信号量mutex提供了对缓冲池访问的互斥要求sem_t empty,full;//信号量empty和full分别表示空缓冲顶和满缓冲顶的个数int pro_speed,con_speed;//可以设定生产者的生产速度及消费者的消费速度int insert_item(buffer_item item){//将生产的产品放入缓冲区buffer[in]=item;printf("******insert缓冲池第%d号******\n",in);inc(in);}int remove_item(buffer_item *item){//从缓冲区内移走一个产品*item = buffer[out];printf("******remove缓冲池第%d号******\n",out);inc(out);}void *producer(void *param){//生产者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-pro_speed));printf("\n******第%d次生产******\n",++num);printf("******等待empty信号******\n");sem_wait(&empty);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备生产******\n");item = rand()%1000+1;printf("******生产产品%d*******\n",item);insert_item(item);printf("*******解锁******\n");printf("******第%d次生产结束*******\n\n",num); pthread_mutex_unlock(&mutex);sem_post(&full);}}void *consumer(void *param){//消费者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-con_speed));printf("\n******第%d次消费*****\n",++num); printf("******等待full信号******\n");sem_wait(&full);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备消费******\n"); remove_item(&item);pthread_mutex_unlock(&mutex);sem_post(&empty);printf("******消费产品%d*******\n",item);printf("*******解锁******\n");printf("******第%d次消费结束*******\n\n",num); }}int main()//主函数{pthread_t tid1,tid2;pthread_attr_t attr1,attr2;srand(time(NULL));pthread_mutex_init(&mutex,NULL);//初始化sem_init(&empty,0,BUFFER_SIZE);sem_init(&full,0,0);in=0;out=0;printf("***********************\n");printf("********开始!***********\n");printf("***********************\n");printf("生产者速度(1-15):\n");scanf("%d",&pro_speed);printf("消费者速度(1-15):\n");scanf("%d",&con_speed);pthread_attr_init(&attr1);pthread_create(&tid1,&attr1,producer,NULL);pthread_attr_init(&attr2);pthread_create(&tid2,&attr2,consumer,NULL);sleep(100);printf("*******程序over*******\n");return 0;}【实验步骤】编写程序代码gedit sx.c,再对代码进行编译gcc sx.c –o sx –lpthread,编译无错误,进行运行./sx,根据提示要求进行填写生产者和消费速度,观察消费者和生产者进程。

【实验结果】【实验体会】 1、Linux 中生成线程方法:第一种方式是用pthread 库来实现的,是在用户程序本身中实现线程,这实际上是对线程的一种模拟,线程之间的切换和调度是在用户的进程内部进行的,这种方式就被称为用户空间的线程。

这种线程的好处是实现非常简单,性能也非常好,因为线程之间的切换都在用户进程内部进行,切换开销比较小。

缺点也非常明显,首先就是不能充分利用高端系统的SMP 多处理器的优点,因为一个进程只能由一个处理器处理,第二点由于用户空间是在用户空间切换,某个线程遇到一个需要阻塞的系统调用进而就会造成这个进程被阻塞,因而所有线程被阻塞。

第二种方式是通过修改进程的实现方式来完成,可以使用不完全的进程创建方式创建共享数据空间的进程,在Linux 下这种系统调用为clone()。

2、Ptrtead 生成线程: POSIX thread 简称为pthread ,Posix 线程是POSIX 标准线程该标准定义内部API 创建和操纵线程。

数据类型pthread_t:线程句柄pthread_attr_t:线程属性线程操纵函数(省略参数):pthread_create():创建一个线程pthread_exit():终止当前线程pthread_cancel():中断另外一个线程的运行pthread_join():阻塞当前的线程,直到另外一个线程运行结束pthread_attr_init():初始化线程的属性pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合)pthread_attr_getdetachstate():获取脱离状态的属性pthread_attr_destroy():删除线程的属性pthread_kill():向线程发送一个信号。

相关主题