生产者与消费者问题(附源码)
计算机操作系统课程设计源代码《生产者---消费者问题源代码》
《生产者---消费者问题源代码》#include<stdio.h>#include<stdlib.h>#include<string.h>#include<pthread.h>#include<semaphore.h>#include<sys/types.h>#include<errno.h>#include<unistd.h>#include<signal.h>#include<time.h>#define NUM_THREADS_P5/*定义数据为生产者*/#define NUM_THREADS_C5/*定义数据为消费者*/#define MAX_BUFFER20/*定义数据为缓存区*/#define RUN_TIME20/*定义运行时间*/int buffer[MAX_BUFFER];/*定义最大缓存区*/int produce_pointer=0,consume_pointer=0;/*定义指针*/sem_t producer_semaphore,consumer_semaphore,buffer_mutex;/*定义信号量,互斥*/pthread_t threads_p[NUM_THREADS_P];/*声明生产者线程*/pthread_t threads_c[NUM_THREADS_C];/*声明消费者线程*/FILE*fd;void*producer_thread(void*tid);/*声明生产者线程*/void*consumer_thread(void*tid);/*声明消费者线程*/void showbuf();/*声明showbuf方法*/void handler(){int i;/*定义i*/for(i=0;i<NUM_THREADS_P;i++)pthread_cancel(threads_p[i]);/*for循环,如果i<NUM_THREADS_P,则pthread_cancel(threads_p[i]);并且i++*/ for(i=0;i<NUM_THREADS_C;i++)pthread_cancel(threads_c[i]);/*for循环,如果i<NUM_THREADS_C,则pthread_cancel(threads_c[i]);并且i++*/}int main(){int i;/*定义i*/signal(SIGALRM,handler);/*定义信号量*/fd=fopen("output.txt","w");/*打开一个文件用来保存结果*/sem_init(&producer_semaphore,0,MAX_BUFFER);/*放一个值给信号灯*/sem_init(&consumer_semaphore,0,0);sem_init(&buffer_mutex,0,1);for(i=0;i<MAX_BUFFER;i++)buffer[i]=0;/*引发缓冲*//*创建线程*/for(i=0;i<NUM_THREADS_P;i++)pthread_create(&threads_p[i],NULL,(void*)producer_thread,(void*)(i+1)); /*创建线程*/for(i=0;i<NUM_THREADS_C;i++)pthread_create(&threads_c[i],NULL,(void*)consumer_thread,(void*)(i+1));alarm(RUN_TIME);for(i=0;i<NUM_THREADS_P;i++)pthread_join(threads_p[i],NULL);/*等待线程退出*/for(i=0;i<NUM_THREADS_C;i++)pthread_join(threads_c[i],NULL);/*等待线程退出*/sem_destroy(&producer_semaphore);/*清除信号灯*/sem_destroy(&consumer_semaphore);/*清除信号灯*/sem_destroy(&buffer_mutex);/*清除缓存区*/fclose(fd);/*关闭文件*/return0;}void*producer_thread(void*tid){pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);/*设置状态,PTHREAD_CANCEL_ENABLE是正常处理cancel信号*/ while(1){sem_wait(&producer_semaphore);/*等待,需要生存*/srand((int)time(NULL)*(int)tid);sleep(rand()%2+1);/*一个或两个需要生产*/while((produce_pointer+1)%20==consume_pointer);/*指针位置*/sem_wait(&buffer_mutex);/*缓存区*/buffer[produce_pointer]=rand()%20+1;/*指针位置*/produce_pointer=(produce_pointer+1)%20;/*指针位置*//*判断*/if(produce_pointer==0){printf("生产者:%d指针指向:%2d生产产品号:%2d\n",(int)tid,19,buffer[19]);/*输出生产者,指针,缓存区*/fprintf(fd,"生产者:%d指针指向:%2d生产产品号:%2d\n",(int)tid,19,buffer[19]);/*输出生产者,指针,缓存区*/}else{printf("生产者:%d指针指向:%2d生产产品号:%2d\n",(int)tid,produce_pointer-1,buffer[produce_pointer-1]);/*输出生产者,指针,缓存区*/fprintf(fd,"生产者:%d指针指向:%2d生产产品号:%2d\n",(int)tid,produce_pointer-1,buffer[produce_pointer-1]);/*输出生产者,指针,缓存区*/}showbuf();sem_post(&buffer_mutex);sem_post(&consumer_semaphore);/*通知消费者缓冲区不是空的*/srand((int)time(NULL)*(int)tid);sleep(rand()%5+1);/*等待几秒钟,然后继续生产*/}return((void*)0);}void*consumer_thread(void*tid){/*可以被其他线程使用*/pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);/*设置状态,PTHREAD_CANCEL_ENABLE是忽略cancel信号*/while(1){sem_wait(&consumer_semaphore);/*通知消费者消费*/srand((int)time(NULL)*(int)tid);sleep(rand()%2+1);/*一个或两个来消费*/sem_wait(&buffer_mutex);printf("消费者:%d指针指向:%2d消费产品号:%2d\n",(int)tid,consume_pointer,buffer[consume_pointer]);/*输出消费者,消费者指针,缓存区*/fprintf(fd,"消费者:%d指针指向:%2d消费产品号:%2d\n",(int)tid,consume_pointer,buffer[consume_pointer]);/*输出消费者,消费者指针,缓存区*/buffer[consume_pointer]=0;/*消费者指针指向0*/consume_pointer=(consume_pointer+1)%20;showbuf();sem_post(&buffer_mutex);sem_post(&producer_semaphore);/*通知生产者缓冲区不是空的*/srand((int)time(NULL)*(int)tid);sleep(rand()%5+1);/*等待几秒钟,然后继续消费*/}return((void*)0);}/*查看缓冲区内容*/void showbuf(){int i;/*定义i*/printf("buffer:");/*输出缓存区*/fprintf(fd,"buffer:");/*输出缓存区*/for(i=0;i<MAX_BUFFER;i++){printf("%2d",buffer[i]);/*输出缓存区i*/fprintf(fd,"%2d",buffer[i]);/*输出缓存区i*/ }printf("\n\n");/*换行*/fprintf(fd,"\n\n");/*换行*/}。
【8A版】C语言编程模拟生产者和消费者问题(附代码程序)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1)PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedurep(vars:semaphore);begins:=s-1;ifs<0thenW(s)end{p}procedurev(vars:semaphore);egins:=s+1;ifs 0thenR(s)end{v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2)生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
C语言编程模拟生产者和消费者问题(附代码程序)(2)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语一一同步原语一一所组成。
本实习要求学生模拟PV 操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0 专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者一一消费者问题。
[提示]:(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedurep(vars:semaphore);begi ns:=s-1;ifs<Othe nW(s)en d{p}procedurev(vars:semaphore);egin s:=s+1;ifs -0thenR(s)en d{v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore 直接改成integer 。
(2) 生产者一一消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
C语言编程模拟生产者与消费者问题附代码程序
添加标题 添加标题
性能优化总结:在实现过程中,我们采用了多线程和并发等机制,提高了程序的运行效率和响 应速度,同时也考虑了程序的稳定性和可靠性。
展望未来:在未来的工作中,我们可以进一步探索和研究生产者与消费者问题及其解决方案, 例如使用更高级的并发和分布式技术,提高程序的性能和可扩展性。同时,也可以将该问题 及其解决方案应用于其他领域,例如操作系统、网络通信和数据库等。
消费者从共享缓冲区取出数 据的代码示例
消费者从共享缓冲区取出数 据的过程分析
消费者从共享缓冲区取出数 据需要注意的问题
添加同步机制(互斥锁、条件变量)
互斥锁的使用:通过互斥锁可以保证同一时间只有一个线程可以访问 共享资源,避免数据冲突。
条件变量的使用:条件变量可以用于实现线程间的同步,一个线程可 以在条件变量上等待,直到另一个线程发出通知。
代码程序运行结果展 示
第五章
程序运行截图
生产者程序运行截图
消费者程序运行截图
生产者与消费者程序运行截 图
程序运行结果展示
程序运行结果描述
生产者与消费者问题的模拟过程 代码程序的运行结果展示 生产者与消费者问题的解决效果 代码程序的运行效率和性能评估
结果分析
展示代码程序运行结果 分析代码程序的执行过程 解释代码程序对生产者与消费者问题的解决过程 总结代码程序的优缺点及改进方向
创建生产者线程
生产者线程执行逻辑
生产者线程与消费者 线程交互
生产者线程结束
消费者线程代码实现
创建消费者线程
消费者线程调用 生产者线程
消费者线程接收 生产者线程发送 的消息
消费者线程处理 接收到的消息
共享资源代码实现
共享资源定义:共享资源是生产者和消费者共同使用的资源,需要保证 在任何时刻都不会被多个生产者或消费者同时访问
生产者与消费者问题(附源码)
操作系统实验报告专业网络工程班级08102 学号姓名课程名称操作系统学年2010-2011 学期下课程类别专业必修■限选□任选□实践□实验时间2010年11月3日实验名称实验一:生产者与消费者问题实验目的和要求全面理解生产者与消费者问题模型,掌握解决该问题的算法思想,正确使用同步机制。
实验软硬件要求Pentium ||| 450以上CPU 64MB以上内存WINDOWS XPVisual C++6.0实验内容、方法和步骤(可附页)问题描述:一组生产者向一组消费者提供商品,共享一个有界缓冲池,生产者向其中放入商品,消费者从中取得商品。
假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将商品送入缓冲池;只要缓冲池未空,消费者可从缓冲池取走一商品。
功能要求:根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放商品、取商品等过程。
具体参数:3个生产者进程,2个消费者进程;缓冲区单元个数N=4;在本程序中是缓冲区中的数从0变为1表示模拟生产一个产品,消费时则将对应缓冲区内的1变为0,为模拟消费一个产品。
实验结果(可附页)见截图小结这次多线程的操作系统实验,使我对线程的概念以及多线程程序中线程间的运行有了更深的认识,同时也让我的编程能力得到了一定的提高。
这次做的用多线程实现生产者与消费者模型的实验,由于我的编程能力基础比较差,对线程也是一无所知,所以一开始觉得无从下手,但幸好老师给了充足的时间,我通过看网上找的视频资料以及请教同学才渐渐地有了一点概念,然后我试着从网上下了一些多线程的程序分析里面的语句,基本弄懂了多线程的原理。
评定成绩:批阅教师:年月日一、问题概述三个生产者向两个消费者提供消息,它们共享一个有界缓冲池,缓冲池有四个缓冲区,生产者向其中投放消息,消费者从中取得消息。
假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将消息送入缓冲池;只要缓冲池未空,消费者可从缓冲池取走一个消息。
C语言编程模拟生产者和消费者问题(附代码程序)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和Visual C++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V (s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedure p (var s: semaphore);begin s: = s-1;if s<0 then W (s)end {p}procedure v (var s: semaphore);egin s: = s+1;if s 0 then R (s)end {v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2) 生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
【8A版】C语言编程模拟生产者和消费者问题(附代码程序)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1)PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedurep(vars:semaphore);begins:=s-1;ifs<0thenW(s)end{p}procedurev(vars:semaphore);egins:=s+1;ifs 0thenR(s)end{v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2)生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
C语言编程模拟生产者和消费者问题(附代码程序)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流P s这两条原语是如下的两个过程:procedure p (var s: semaphore);begin s: = s-1;if s<0 then W (s)end {p}procedure v (var s: semaphore);精心整理egin s: = s+1;if s 0 then R (s)end {v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
V (s2);goto L1end;procedure consumer;x: products;begin精心整理L2: p (s2);x: =B[out];out: =(out+1) mod10;v (s1);consume (x);goto L2end;integer运行态、中保留精心整理入口地址;每个SA[i]存放消费者程序中的一条模拟指令执行的入口地址。
于是模拟处理器执行一条指令的过程为:取出PC之值,按PA[PC]或SA[PC]得模拟指令执行的入口地址,将PC之值加1,转向由入口地址确定的相应的过程执行。
精心整理精心整理精心整理图3-3 生产者和消费者程序(5) 程序设计精心整理精心整理本实习中的程序由三部分组成:初始化程序、处理器调度程序、模拟处理器指令执行程序。
各部分程序的功能及相互间的关系由图3-4至图3-7指出。
图3-5 模拟处理器调度·初始化程序:模拟实习的程序从初始化程序入口启动,初始化工作包括对信号量s1、s2赋初值,对生产者、消费者进程的PCB 初始化。
C语言编程模拟生产者和消费者问题(附代码程序)
C语言编程模拟生产者和消费者问题(附代码程序)实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语一一同步原语一一所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者一一消费者问题。
[提示]:⑴PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedurep(vars:semaphore);begi ns:=s-1;ifs<0the nW(s)en d{p}procedurev(vars:semaphore);egin s:=s+1;ifs _Othe nR(s)en d{v}其中W (s)表示将调用过程的进程置为等待信号量s的状态;R (s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2) 生产者一一消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
编程模拟生产者和消费者问题附代码程序
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和Visual C++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V (s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedure p (var s: semaphore);begin s: = s-1;if s<0 then W (s)end {p}procedure v (var s: semaphore);egin s: = s+1;if s 0 then R (s)end {v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2) 生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
[实用参考]C语言编程模拟生产者和消费者问题(附代码程序)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1)PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedurep(vars:semaphore);begins:=s-1;ifs<0thenW(s)end{p}procedurev(vars:semaphore);egins:=s+1;ifs 0thenR(s)end{v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2)生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
C语言编程模拟生产者和消费者问题(附代码程序)(2)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语一一同步原语一一所组成。
本实习要求学生模拟PV 操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0 专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者一一消费者问题。
[提示]:(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedurep(vars:semaphore);begi ns:=s-1;ifs<Othe nW(s)en d{p}procedurev(vars:semaphore);egin s:=s+1;ifs -0thenR(s)en d{v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore 直接改成integer 。
(2) 生产者一一消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
操作系统实验 生产者与消费者问题
实验一生产者和消费者问题1、程序流程图2、源代码#include <windows.h>#include <iostream>const unsigned short SIZE_OF_BUFFER = 10;unsigned short ProductID = 0;unsigned short ConsumeID = 0;unsigned short in = 0;unsigned short out = 0;int g_buffer[SIZE_OF_BUFFER];bool g_continue = true;HANDLE g_hMutex;HANDLE g_hFullSemaphore;HANDLE g_hEmptySemaphore;DWORD WINAPI Producer(LPVOID);DWORD WINAPI Consumer(LPVOID);int main(){ g_hMutex = CreateMutex(NULL,FALSE,NULL);g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);const unsigned short PRODUCERS_COUNT = 3;const unsigned short CONSUMERS_COUNT = 1;const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;HANDLE hThreads[PRODUCERS_COUNT];DWORD producerID[CONSUMERS_COUNT];DWORD consumerID[THREADS_COUNT];for (int i=0;i<PRODUCERS_COUNT;++i){hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if (hThreads[i]==NULL) return -1;}for ( i=0;i<CONSUMERS_COUNT;++i){hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);if (hThreads[i]==NULL) return -1;}while(g_continue){if(getchar()){ //按回车后终止程序运行g_continue = false;}}return 0;}void Produce(){ std::cerr << "Producing " << ++ProductID << " ... ";std::cerr << "Succeed" << std::endl;}void Append(){ std::cerr << "Appending a product ... ";g_buffer[in] = ProductID;in = (in+1)%SIZE_OF_BUFFER;std::cerr << "Succeed" << std::endl;for (int i=0;i<SIZE_OF_BUFFER;++i){std::cout << i <<": " << g_buffer[i];if (i==in) std::cout << " <-- 生产";if (i==out) std::cout << " <-- 消费";std::cout << std::endl;}}void Take(){ std::cerr << "Taking a product ... ";ConsumeID = g_buffer[out];out = (out+1)%SIZE_OF_BUFFER;std::cerr << "Succeed" << std::endl;for (int i=0;i<SIZE_OF_BUFFER;++i){std::cout << i <<": " << g_buffer[i];if (i==in) std::cout << " <-- 生产";if (i==out) std::cout << " <-- 消费";std::cout << std::endl; }}void Consume(){ std::cerr << "Consuming " << ConsumeID << " ... ";std::cerr << "Succeed" << std::endl;}DWORD WINAPI Producer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hFullSemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Produce();Append();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);}return 0;}DWORD WINAPI Consumer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hEmptySemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Take();Consume();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hFullSemaphore,1,NULL);}return 0;}3、实验结果3、实验心得通过做生产者消费者问题这个实验,让我更加明确了两者之间的联系和基本的同步互斥算法,了解多线程并发执行机制是怎样的,线程间的同步和互斥又是怎样的,还有缓冲区的在其中作用是什么。
【名师精品】C语言编程模拟生产者和消费者问题(附代码程序).doc
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1)PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:pYoceduYep(vaYs:semaphoYe);begins:=s-1;ifs<0thenW(s)end{p}pYoceduYev(vaYs:semaphoYe);egins:=s+1;ifs 0thenY(s)end{v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;Y(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphoYe定义为某个类型,为简单起见,在模拟实习中可把上述的semaphoYe直接改成integeY。
(2)生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
C语言编程模拟生产者和消费者问题(附代码程序)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Window s操作系统和Visu al C++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V (s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:proced ure p (var s: semaph ore);begins: = s-1;if s<0 then W (s)end {p}proced ure v (var s: semaph ore);egin s: = s+1;if s 0 then R (s)end {v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
【8A版】C语言编程模拟生产者和消费者问题(附代码程序)
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和VisualC++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1)PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P(s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V(s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedurep(vars:semaphore);begins:=s-1;ifs<0thenW(s)end{p}procedurev(vars:semaphore);egins:=s+1;ifs 0thenR(s)end{v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2)生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
生产者消费者问题代码
生产者消费者问题用vc++实现悬最佳答案#include<windows.h>#include<fstream.h>#include<stdio.h>#include<string>#include<conio.h>//定义一些常量;//本程序允许的最大临界区数;#define MAX_BUFFER_NUM 10//秒到微秒的乘法因子;#define INTE_PER_SEC 1000//本程序允许的生产和消费线程的总数;#define MAX_THREAD_NUM 64//定义一个结构,记录在测试文件中指定的每一个线程的参数struct ThreadInfo{int serial; //线程序列号char entity; //是P还是Cdouble delay; //线程延迟int thread_request[MAX_THREAD_NUM]; //线程请求队列int n_request; //请求个数};//全局变量的定义//临界区对象的声明,用于管理缓冲区的互斥访问;CRITICAL_SECTION PC_Critical[MAX_BUFFER_NUM];int Buffer_Critical[MAX_BUFFER_NUM]; //缓冲区声明,用于存放产品;HANDLE h_Thread[MAX_THREAD_NUM]; //用于存储每个线程句柄的数组;ThreadInfo Thread_Info[MAX_THREAD_NUM]; //线程信息数组;HANDLE empty_semaphore; //一个信号量;HANDLE h_mutex; //一个互斥量;DWORD n_Thread = 0; //实际的线程的数目;DWORD n_Buffer_or_Critical; //实际的缓冲区或者临界区的数目;HANDLE h_Semaphore[MAX_THREAD_NUM]; //生产者允许消费者开始消费的信号量;//生产消费及辅助函数的声明void Produce(void *p);void Consume(void *p);bool IfInOtherRequest(int);int FindProducePositon();int FindBufferPosition(int);int main(void){//声明所需变量;DWORD wait_for_all;ifstream inFile;//初始化缓冲区;for(int i=0;i< MAX_BUFFER_NUM;i++)Buffer_Critical[i] = -1;//初始化每个线程的请求队列;for(int j=0;j<MAX_THREAD_NUM;j++){for(int k=0;k<MAX_THREAD_NUM;k++)Thread_Info[j].thread_request[k] = -1;Thread_Info[j].n_request = 0;}//初始化临界区;for(i =0;i< MAX_BUFFER_NUM;i++)InitializeCriticalSection(&PC_Critical[i]);//打开输入文件,按照规定的格式提取线程等信息;inFile.open("test.txt");//从文件中获得实际的缓冲区的数目;inFile >> n_Buffer_or_Critical;inFile.get();printf("输入文件是:\n");//回显获得的缓冲区的数目信息;printf("%d \n",(int) n_Buffer_or_Critical);//提取每个线程的信息到相应数据结构中;while(inFile){inFile >> Thread_Info[n_Thread].serial;inFile >> Thread_Info[n_Thread].entity;inFile >> Thread_Info[n_Thread].delay;char c;inFile.get(c);while(c!='\n'&& !inFile.eof()){inFile>>Thread_Info[n_Thread].thread_request[Thread_Info[n_Thread].n_request++];inFile.get(c);}n_Thread++;}//回显获得的线程信息,便于确认正确性;for(j=0;j<(int) n_Thread;j++){int Temp_serial = Thread_Info[j].serial;char Temp_entity = Thread_Info[j].entity;double Temp_delay = Thread_Info[j].delay;printf(" \n thread%2d %c %f",Temp_serial,Temp_entity,Temp_delay);int Temp_request = Thread_Info[j].n_request;for(int k=0;k<Temp_request;k++)printf(" %d ", Thread_Info[j].thread_request[k]);cout<<endl;}printf("\n\n");//创建在模拟过程中几个必要的信号量empty_semaphore=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buffer_or _Critical,"semaphore_for_empty");h_mutex = CreateMutex(NULL,FALSE,"mutex_for_update");//下面这个循环用线程的ID号来为相应生产线程的产品读写时所//使用的同步信号量命名;for(j=0;j<(int)n_Thread;j++){std::string lp ="semaphore_for_produce_";int temp =j;while(temp){char c = (char)(temp%10);lp+=c;temp/=10;}h_Semaphore[j+1]=CreateSemaphore(NULL,0,n_Thread,lp.c_str());}//创建生产者和消费者线程;for(i =0;i< (int) n_Thread;i++){if(Thread_Info[i].entity =='P')h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Produce), &(Thread_Info[i]),0,NULL);elseh_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consu me),&(Thread_Info[i]),0,NULL);}//主程序等待各个线程的动作结束;wait_for_all = WaitForMultipleObjects(n_Thread,h_Thread,TRUE,-1); printf(" \n \nALL Producer and consumer have finished their work. \n"); printf("Press any key to quit!\n");_getch();return 0;}//确认是否还有对同一产品的消费请求未执行;bool IfInOtherRequest(int req){for(int i=0;i<n_Thread;i++)for(int j=0;j<Thread_Info[i].n_request;j++)if(Thread_Info[i].thread_request[j] == req)return TRUE;return FALSE;}//找出当前可以进行产品生产的空缓冲区位置;int FindProducePosition(){int EmptyPosition;for (int i =0;i<n_Buffer_or_Critical;i++)if(Buffer_Critical[i] == -1){EmptyPosition = i;//用下面这个特殊值表示本缓冲区正处于被写状态;Buffer_Critical[i] = -2;break;}return EmptyPosition;}//找出当前所需生产者生产的产品的位置;int FindBufferPosition(int ProPos){int TempPos;for (int i =0 ;i<n_Buffer_or_Critical;i++)if(Buffer_Critical[i]==ProPos){TempPos = i;break;}return TempPos;}//生产者进程void Produce(void *p){//局部变量声明;DWORD wait_for_semaphore,wait_for_mutex,m_delay;int m_serial;//获得本线程的信息;m_serial = ((ThreadInfo*)(p))->serial;m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);Sleep(m_delay);//开始请求生产printf("Producer %2d sends the produce require.\n",m_serial);//确认有空缓冲区可供生产,同时将空位置数empty减1;用于生产者和消费者的同步;wait_for_semaphore = WaitForSingleObject(empty_semaphore,-1);//互斥访问下一个可用于生产的空临界区,实现写写互斥;wait_for_mutex = WaitForSingleObject(h_mutex,-1);int ProducePos = FindProducePosition();ReleaseMutex(h_mutex);//生产者在获得自己的空位置并做上标记后,以下的写操作在生产者之间可以并发;//核心生产步骤中,程序将生产者的ID作为产品编号放入,方便消费者识别; printf("Producer %2d begin to produce atposition %2d.\n",m_serial,ProducePos);Buffer_Critical[ProducePos] = m_serial;printf("Producer %2d finish producing :\n ",m_serial);printf(" position[ %2d ]:%3d \n" ,ProducePos,Buffer_Critical[ProducePos]); //使生产者写的缓冲区可以被多个消费者使用,实现读写同步;ReleaseSemaphore(h_Semaphore[m_serial],n_Thread,NULL);}//消费者进程void Consume(void * p){//局部变量声明;DWORD wait_for_semaphore,m_delay;int m_serial,m_requestNum; //消费者的序列号和请求的数目;int m_thread_request[MAX_THREAD_NUM];//本消费线程的请求队列;//提取本线程的信息到本地;m_serial = ((ThreadInfo*)(p))->serial;m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);m_requestNum = ((ThreadInfo *)(p))->n_request;for (int i = 0;i<m_requestNum;i++)m_thread_request[i] = ((ThreadInfo*)(p))->thread_request[i];Sleep(m_delay);//循环进行所需产品的消费for(i =0;i<m_requestNum;i++){//请求消费下一个产品printf("Consumer %2d request to consume %2dproduct\n",m_serial,m_thread_request[i]);//如果对应生产者没有生产,则等待;如果生产了,允许的消费者数目-1;实现了读写同步;wait_for_semaphore=WaitForSingleObject(h_Semaphore[m_thread_request[i] ],-1);//查询所需产品放到缓冲区的号int BufferPos=FindBufferPosition(m_thread_request[i]);//开始进行具体缓冲区的消费处理,读和读在该缓冲区上仍然是互斥的;//进入临界区后执行消费动作;并在完成此次请求后,通知另外的消费者本处请求已//经满足;同时如果对应的产品使用完毕,就做相应处理;并给出相应动作的界面提//示;该相应处理指将相应缓冲区清空,并增加代表空缓冲区的信号量;EnterCriticalSection(&PC_Critical[BufferPos]);printf("Consumer%2d begin to consume %2d product\n",m_serial,m_thread_request[i]);((ThreadInfo*)(p))->thread_request[i] =-1;if(!IfInOtherRequest(m_thread_request[i])){Buffer_Critical[BufferPos] = -1;//标记缓冲区为空;printf("Consumer%2d finish consuming %2d:\n",m_serial,m_thread_request[i]);printf(" position[ %2d ]:%3d \n" ,BufferPos,Buffer_Critical[BufferPos]); ReleaseSemaphore(empty_semaphore,1,NULL);}else{printf("Consumer %2d finish consuming product %2d\n",m_serial,m_thread_request[i]);}//离开临界区LeaveCriticalSection(&PC_Critical[BufferPos]);}}8。
C语言编程模拟生产者及消费者问题[附代码程序]
实验三编程模拟生产者和消费者问题一、实验目的和要求模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
二、实验环境Windows操作系统和Visual C++6.0专业版或企业版三、实验步骤模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V (s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedure p (var s: semaphore);begin s: = s-1;if s<0 then W (s)end {p}procedure v (var s: semaphore);egin s: = s+1;if s 0 then R (s)end {v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2) 生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统实验报告专业网络工程班级08102 学号姓名课程名称操作系统学年2010-2011 学期下课程类别专业必修■限选□任选□实践□实验时间2010年11月3日实验名称实验一:生产者与消费者问题实验目的和要求全面理解生产者与消费者问题模型,掌握解决该问题的算法思想,正确使用同步机制。
实验软硬件要求Pentium ||| 450以上CPU 64MB以上内存WINDOWS XPVisual C++6.0实验内容、方法和步骤(可附页)问题描述:一组生产者向一组消费者提供商品,共享一个有界缓冲池,生产者向其中放入商品,消费者从中取得商品。
假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将商品送入缓冲池;只要缓冲池未空,消费者可从缓冲池取走一商品。
功能要求:根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放商品、取商品等过程。
具体参数:3个生产者进程,2个消费者进程;缓冲区单元个数N=4;在本程序中是缓冲区中的数从0变为1表示模拟生产一个产品,消费时则将对应缓冲区内的1变为0,为模拟消费一个产品。
实验结果(可附页)见截图小结这次多线程的操作系统实验,使我对线程的概念以及多线程程序中线程间的运行有了更深的认识,同时也让我的编程能力得到了一定的提高。
这次做的用多线程实现生产者与消费者模型的实验,由于我的编程能力基础比较差,对线程也是一无所知,所以一开始觉得无从下手,但幸好老师给了充足的时间,我通过看网上找的视频资料以及请教同学才渐渐地有了一点概念,然后我试着从网上下了一些多线程的程序分析里面的语句,基本弄懂了多线程的原理。
评定成绩:批阅教师:年月日一、问题概述三个生产者向两个消费者提供消息,它们共享一个有界缓冲池,缓冲池有四个缓冲区,生产者向其中投放消息,消费者从中取得消息。
假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将消息送入缓冲池;只要缓冲池未空,消费者可从缓冲池取走一个消息。
每个缓冲设有一个所标记,生产者在生产产品以前要先判断缓冲区是否已上锁,消费者在消费产品之前也要进行判断。
二、设计流程图主要流程:1、生产者进程生产流程图,如图1所示图1 生产者进程生产流程图2、消费者进程消费流程图,如图2所示图2 消费者进程消费流程图三、数据定义bool lock[4]={false,false,false,false};//四把锁,分别对四个缓冲区进行控制int buffer[4]={0,0,0,0};//缓冲区个数为4四、源程序1、生产者生产进程函数DWORD WINAPI Producer(LPVOID lpParameter){while(true){for(int j=0;j<4;j++){if(buffer[j]==0){//找到空缓冲区if(lock[j]==false){//同步锁为false,可以进行操作lock[j]=true;//加锁,防止其他线程操作此缓冲区if(buffer[j]<1){//限定一个缓冲区只能存放一个资源++buffer[j];//模拟生产资源cout<<"生产一个资源,放入缓冲区"<<j<<"中"<<endl;lock[j]=false;//解锁break;//一次生产一个}}if(j==3){cout<<"找不到空缓冲区,等待中。
"<<endl;Sleep(2000);}}}}return 0;}2、消费者消费进程函数DWORD WINAPI Customer(LPVOID lpParameter){while(true){for(int n=0;n<4;n++){if(buffer[n]==1){//找到满缓冲区if(lock[n]==false){//同步锁为false,可以进行操作lock[n]=true;//加锁,防止其他线程操作此缓冲区if(buffer[n]>=1){--buffer[n];//模拟消费资源cout<<"消费一个资源,从缓冲区"<<n<<"中取出"<<endl;lock[n]=false;//解锁break;//一次生产一个}}}if(n==3){cout<<"找不到满缓冲区,等待中。
"<<endl;Sleep(2000);}}}}3、主函数,创建5个进程,其中3个生产者进程,2个消费者进程int main(int argc,char* argv[]){HANDLE handle[3];DWORD dw1,dw2,dw3,dw4,dw5;//创建5个进程handle[0]=CreateThread(NULL,0,Producer,NULL,0,&dw1);handle[1]=CreateThread(NULL,0,Producer,NULL,0,&dw2);handle[2]=CreateThread(NULL,0,Producer,NULL,0,&dw3);handle[3]=CreateThread(NULL,0,Customer,NULL,0,&dw4);handle[4]=CreateThread(NULL,0,Customer,NULL,0,&dw5);}五、运行结果3个生产者2个消费者,共享4个缓冲区,运行结果如下:1、一个生产者生产,一个消费者消费:2、两个生产者连续生产,两个消费者连续消费:3、多个生产者于多个消费者进行生产消费操作:附:#include "iostream.h"#include "windows.h"#include "stdio.h"bool lock[4]={false,false,false,false};//四把锁,分别对四个缓冲区进行同步int buffer[4]={0,0,0,0};//缓冲区,表示资源的个数void display(){cout<<"--------------------------------"<<endl;cout<<"缓冲区0 1 2 3"<<endl;for(int i=0;i<4;i++){cout<<" "<<buffer[i]<<" ";}cout<<endl;}DWORD WINAPI Producer(LPVOID lpParameter){while(true){for(int j=0;j<4;j++){if(buffer[j]==0){//找到空缓冲区if(lock[j]==false){//同步锁为false,可以进行操作lock[j]=true;//加锁,防止其他线程操作此缓冲区if(buffer[j]<1){//限定一个缓冲区只能存放一个资源++buffer[j];//模拟生产资源cout<<"生产一个资源,放入缓冲区"<<j<<"中"<<endl;lock[j]=false;//解锁break;//一次生产一个}}if(j==3){cout<<"找不到空缓冲区,等待中。
"<<endl;Sleep(2000);}}}}return 0;}DWORD WINAPI Customer(LPVOID lpParameter){while(true){for(int n=0;n<4;n++){if(buffer[n]==1){//找到满缓冲区if(lock[n]==false){//同步锁为false,可以进行操作lock[n]=true;//加锁,防止其他线程操作此缓冲区if(buffer[n]>=1){--buffer[n];//模拟消费资源cout<<"消费一个资源,从缓冲区"<<n<<"中取出"<<endl;lock[n]=false;//解锁break;//一次生产一个}}}if(n==3){cout<<"找不到满缓冲区,等待中。
"<<endl;Sleep(2000);}}}return 0;}int main(int argc,char* argv[]){display();HANDLE handle[3];DWORD dw1,dw2,dw3,dw4,dw0;handle[0]=CreateThread(NULL,0,Producer,NULL,0,&dw1);handle[1]=CreateThread(NULL,0,Producer,NULL,0,&dw2);handle[2]=CreateThread(NULL,0,Producer,NULL,0,&dw3);handle[3]=CreateThread(NULL,0,Customer,NULL,0,&dw4);handle[4]=CreateThread(NULL,0,Customer,NULL,0,&dw0);display();Sleep(3000);display();return 0;}。