操作系统生产者与消费者课程设计

合集下载

生产者消费者课程设计

生产者消费者课程设计

生产者消费者课程设计一、课程目标知识目标:1. 学生理解生产者与消费者的基本概念,掌握它们在生态系统中的作用与相互关系。

2. 学生能够描述食物链与食物网的结构,并识别其中的生产者和消费者。

3. 学生了解生态系统中物质与能量的流动过程。

技能目标:1. 学生能够通过观察与实验分析,识别并区分生态系统中的生产者和消费者。

2. 学生具备绘制食物链和食物网的能力,并能用其解释生态系统中物质能量的传递。

3. 学生能够运用所学知识解决有关生产者消费者的实际问题。

情感态度价值观目标:1. 学生培养对生态系统的尊重与保护意识,认识到生产者消费者在其中的重要角色。

2. 学生通过学习小组合作,增强团队协作意识,培养科学探究精神。

3. 学生在探索生态学知识的过程中,激发对生命科学的好奇心与学习兴趣,形成积极的学习态度。

课程性质分析:本课程为生态学基础知识教学,通过讲解生产者与消费者的概念,使学生建立对生态系统基本构成的理解,并培养其分析和解决实际生态问题的能力。

学生特点分析:考虑到学生所在年级,已具备一定的观察、思考与自主学习能力,对新知识充满好奇心,但可能缺乏将理论知识应用于实际情境的经验。

教学要求:1. 教学内容紧密结合课本知识,以实例进行引导,提高学生对概念的理解。

2. 教学过程注重启发式教学,引导学生主动探究,提高其分析问题和解决问题的能力。

3. 教学评价关注学生的过程表现,强调知识的应用与实践,以及情感态度价值观的培养。

二、教学内容本课程依据课程目标,结合课本第三章“生态系统的结构与功能”相关内容,进行以下教学安排:1. 引入生态系统的基本概念,重点讲解生产者与消费者的定义、特点及作用。

- 教材章节:第三章第一节“生态系统的基本概念”2. 通过案例分析,使学生掌握食物链与食物网的结构,并理解其中的物质能量流动。

- 教材章节:第三章第二节“食物链与食物网”3. 介绍生态系统中物质与能量的转化过程,分析生产者与消费者在其中的角色。

生产者和消费者课程设计

生产者和消费者课程设计
2、数据结构及信号量定义的说明;
3、实验的步骤;
4、实验源程序关键算法;
5、实验运行图;
6、实验结果分析;
六、结论(应当准确、完整、明确精练;也可以在结论或讨论中提出建议、设想、尚待解决问题等。)
七、参考文献
八、指导教师评语
签名:
年月日
课程设计成绩
附:1、课程设计的填写请按格式要求做;
2、文字内容宋体、五号、1.5倍行距;
2、培养学生能够独立进行知识综合,独立开发较大程序的能力。
3、培养提高学生软件开发能力和软件的调试技术。
4、培养学生开发大型程序的方法和相互合作的精神。
5、培养学生的创新意识。
6、培养学生的算法设计和算法分析能力。
7、培养学生对问题进行文字论述和文字表达的能力。
二、课程设计的内容及其要求
1、可利用临界区(CCriticalSection)、事件(CEvent)、信号量(CSemaphore)来实现进程的同步。
2、根据生产者和消费者问题的特性做好软件实现的需要分析。
3、可根据问题的实际需要,来改变对信号量的使用及数量和初值的赋值。
4、当系统运行时,能直观地、动态地反映当前线程运行的状态和信号量的变化。
5、要求系统能满足能多进程的并发与互斥。
6、要求在系统安全状态的前提下,兼顾各个进程的公平。
三、课程设计的时间安排
3、程序代码字体Times New Roman,五号、1.5倍行距;
《操作系统》课程设计
生产者和消费者问题实践
系院:信息工程学院
学生姓名:xxxxxxx
学号:xxxxxxxxxxxx
专业:xxxxxxxxxxxx
年级:xxxxxxx
完成日期:xxxx年xx月

操作系统_生产者和消费者

操作系统_生产者和消费者

《操作系统》课程设计生产者和消费者的问题学院:计算机学院学生姓名:屈杨学号:5409216018专业:计算机科学技术其中实验数据是:3附件:原程序代码#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)(Consume),&(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 at position %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 %2d product\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]);}}。

生产者消费者问题操作系统课程设计

生产者消费者问题操作系统课程设计

目录1 绪论 (1)1.1 实现的功能 (1)1.2 P V 操作 (1)2 生产者——消费者问题。

(2)2.1 要求 (2)2.2 生产者和消费者两个进程的程序 (2)2.3进程控制块PCB。

(3)2.4处理器的模拟。

(3)2.5程序设计 (3)3设计步骤 (4)3.1课程分析 (5)3.1.2 流程图 (5)3.1.3 测试程序 (7)3.1.4测试结果分析 (12)5 结论 (12)参考文献 (13)1 绪论生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。

模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。

进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。

我们把若干个进程都能进行访问和修改的那些变量称为公共变量。

由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。

为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。

一般说,同步机构是由若干条原语——同步原语——所组成。

本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。

1.1 实现的功能生产者-消费者问题是一个经典的进程同步问题,有m个生产者和n个消费者,它们共享可存放k件产品的缓冲区。

生产者进程生产物品,然后将物品放置在一个空缓冲区中,供消费者进程消费。

消费者进程从缓冲区中获得物品,然后释放缓冲区。

当生产者进程生产物品时,如果没有空缓冲区可用,那么生产者进程必须等待消费者线程释放出一个空缓冲区。

当消费者进程消费物品时,如果没有满的缓冲区,那么消费者进程将被阻塞,直到新的物品被生产出来。

1.2 P V 操作(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。

生产者消费者问题实验报告

生产者消费者问题实验报告

操作系统课程设计实验报告实验名称: 生产者消费者问题姓名/学号:一、实验目的以生产者和消费者问题为例, 学习Linux和Windows下进程通信、同步机制的具体实现方法, 主要是信号量和共享内存。

熟悉相关系统API的用法。

二、实验内容使用共享内存和信号量机制来实现多个生产者/消费者进程间的通信和同步。

要求在Linux和Windows下分别实现。

缓冲区大小为3, 初始为空。

2个生产者, 随机等待一段时间, 往缓冲区添加数据, 重复6次。

3个消费者, 重复4次。

三、实验环境Ubuntu 10.10 , GCC; Windows 7, VC 6.0;四、程序设计与实现1.Linux下:(1) 数据结构:a.共享内存定义为一个结构, 使得其数据成员更清晰且操作变得简单。

b.共享缓冲区采用循环队列的数据结构,由上面的结构struct buf { int start; int end; int info[BUF_NUM]; }维护。

其中start为队头指针, end为队尾指针, info为数据区域。

(2) 算法:a.大致由三个模块组成:i.主程序(main):ii.创建信号量、共享内存并进行初始化iii.创建生产者、消费者进程, 生产者执行pro_fun(), 消费者执行con_fun()iv.等待所有子进程的结束v.删除信号量、共享内存i.生产者进程(pro_fun):ii.通过key获得信号量、共享内存的ID, 将内存添加到自己的地址空间iii.P(empty), P(mutex), Add(data), V(mutex), V(full)iv.解除和共享内存的关联i.消费者进程(con_fun):ii.通过key获得信号量、共享内存的ID, 将内存添加到自己的地址空间iii.P(full), P(mutex), Add(data), V(mutex), V(empty)iv.解除和共享内存的关联循环队列部分:加入数据: info[end] = value; end = (end + 1) % 3;取出数据: temp = info[start]; info[start] = 0; (start = start + 1)%3; return temp;(3) 程序流程图:a.主函数:b.生产者进程:c.消费者进程和生产者类似4.Windows 下:(1) 数据结构:和Linux大致相同(2) 算法:a.创建的子进程调用正在执行的文件本身, 通过main函数的参数区分主进程和生产者、消费者进程。

操作系统课程设计“生产者-消费者”问题

操作系统课程设计“生产者-消费者”问题

《操作系统》课程设计题目:“生产者-消费者”问题学院:信息工程学院专业:计算机科学与技术班级:计科1302*名:***指导老师:***2016年1月 15日目录一、课程设计目标 (2)二、课题内容 (2)1.实验目的 (2)2、实验环境 (2)3、实验要求 (2)三、设计思路 (3)1.信号量的设置 (3)2.系统结构 (4)3.程序流程图 (5)4.P V操作代码 (6)四、源代码 (7)五、运行与测试 (10)六、心得体会 (12)一、课程设计目标学习System V的进程间通信机制,使用信号量和共享内存实现经典进程同步问题“生产者-消费者”问题。

具体要求:1.创建信号量集,实现同步互斥信号量。

2.创建共享内存,模拟存放产品的公共缓冲池。

3.创建并发进程,实现进程对共享缓冲池的并发操作。

二、课题内容1.实验目的(1)掌握基本的同步互斥算法,理解生产者和消费者同步的问题模型。

(2)了解linux中多线程的并发执行机制,线程间的同步和互斥。

2、实验环境:C/C++语言编译器3、实验要求(1)创建生产者和消费者线程在linux环境下,创建一个控制台进程,在此进程中创建n个线程来模拟生产者或者消费者。

这些线程的信息由本程序定义的“测试用例文件”中予以指定。

(2)生产和消费的规则在按照上述要求创建线程进行相应的读写操作时,还需要符合以下要求:①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。

②从上边的测试数据文件例子可以看出,某一生产者生产一个产品后,可能不止一个消费者,或者一个消费者多次地请求消费该产品。

此时,只有当所有的消费需求都被满足以后,该产品所在的共享缓冲区才可以被释放,并作为空闲空间允许新的生产者使用。

③每个消费者线程的各个消费需求之间存在先后顺序。

例上述测试用例文件包含一行信息“5 C 3 l 2 4”,可知这代表一个消费者线程,该线程请求消费1,2,4号生产者线程生产的产品。

而这种消费是有严格顺序的,消费1号线程产品的请求得到满足后才能继续往下请求2号生产者线程的产品。

现代操作系统课程设计报告 生产者与消费问题

现代操作系统课程设计报告  生产者与消费问题

进程同步模拟设计——生产者和消费者问题第一章课设任务本课程设计的任务在于,通过编写一个具体的有关操作系统进程同步互斥的经典问题,加强对操作系统实现进程间同步与互斥的机制的理解。

同时培养提出问题、发现知识、使用工具、解决问题的能力。

具体地,我们要编制出一个程序,利用PV原语以及进程创建、同步、互斥、销毁等相关的系统调用来模拟“生产者—消费者”问题。

第二章背景介绍2.1 “生产者—消费者”问题(the producer-consumer problem)生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区。

其中一个是生产者,用于将消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。

问题出现在当缓冲区已经满了,而此时生产者还想向其中放入一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它。

同样地,当缓冲区已经空了,而消费者还想去取消息,此时也可以让消费者进行休眠,等待生产者放入一个或者多个数据时再唤醒它。

问题分析:该问题涉及到操作系统进程管理当中的两个重要概念——同步和互斥。

同步,表现在生产者和消费者需要协同工作,步调不能拉开太大(由缓冲区大小n决定,n越大,缓冲空间越大,步调可以拉得越开;n=1时,必须是生产一个,消费一个,生产者和消费者就完全同步了)。

当步调差距超过极限时,走在前面的当前进程(生产者)调用P 原语时由于资源耗尽,被阻塞;步调靠后的继续向前推进。

由此实现同步。

互斥,表现在生产者与消费者、生产者与生产者、消费者与消费者任何两个成员之间必须互斥地使用缓冲区。

当有一个成员进入缓冲区存/取产品时,其他成员将被关在门外排队等候(被阻塞);当完毕时,通知队首成员进入。

由操作系统理论可知,我们需要三个信号量,分别命名full, empty, mutex,来分别代表消费者的可用资源数、生产者的可用资源数、缓冲区是否可用。

操作系统生产者与消费者课程设计

操作系统生产者与消费者课程设计

操作系统课程设计课题名称:Windows OS平台下的生产者和消费者问题班级:软件学号:姓名:指导教师:成绩:目录一、课程设计目的 (1)二、课程任务描述 (1)三、技术方案 (1)1. 算法分析 (1)2. 技术机制 (4)3. 库函数介绍 (5)4. 运行环境 (7)四、详细设计 (7)1.程序框架 (8)2.数据结构 (10)3. 流程图 (10)五、运行与测试 (11)六、总结及改进意见 (11)七、附录 (11)一、课程设计目的1.理解生产者消费者模型,掌握基本的同步、互斥算法。

2.理解操作系统中进程间通信机制IPC3.掌握以生产者/消费者模型为依据,在Windows环境下创建一个控制台进程,实现进程(线程)的同步与互斥。

4.掌握和使用共享主存实现进程间通信机制。

二、课程任务描述设计一个C+程序,该程序通过线程并发机制创建两类线程,分别是消费者线程和生产者线程,并运用IPC机制,在Windows平台下,使用信号量和共享内存实现“生产者-消费者”问题。

具体要求:1.使用IPC机制创建信号集,实现”生产者-消费者“问题中的同步与互斥。

2.使用IPC机制创建共享内存,模拟存放产品的公共缓冲区。

3.以生产者/消费者模型为依据,在Windows环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。

三、技术方案1.算法分析1)创建生产者和消费者线程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)(Consume),& (Thread_Info[i]),0,NULL);}2)生产者进程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 at position %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);}3)消费者进程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 %2d product\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]);}}2.技术机制有一个有限缓冲区和多个线程:生产者和消费者。

《操作系统》课程设计说明书_用多线程同步方法解决生产者-消费者问题

《操作系统》课程设计说明书_用多线程同步方法解决生产者-消费者问题

目录目录 (1)用多线程同步方法解决生产者-消费者问题 (3)1. 设计题目与要求 (3)1.1设计题目 (3)1.2设计要求 (3)2.设计思想及系统平台 (3)2.1设计思想 (3)2.2系统平台及使用语言 (3)3.数据结构与模块说明 (4)4.源程序清单 (7)5.运行结果与运行情况 (12)6.调试过程.................................................................................................... 错误!未定义书签。

7.总结 (16)本科生课程设计成绩评定表 (18)课程设计任务书学生姓名:专业班级:指导教师:工作单位:计算机科学与技术学院题目: 用多线程同步方法解决生产者-消费者问题 (Producer-Consumer Problem)初始条件:1.操作系统:Linux2.程序设计语言:C语言3.有界缓冲区内设有20个存储单元,其初值为0。

放入/取出的数据项按增序设定为1-20这20个整型数。

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.技术要求:1)为每个生产者/消费者产生一个线程,设计正确的同步算法2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的当前全部内容、当前指针位置和生产者/消费者线程的自定义标识符。

3)生产者和消费者各有两个以上。

4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。

2.设计说明书内容要求:1)设计题目与要求2)总的设计思想及系统平台、语言、工具等。

3)数据结构与模块说明(功能与流程图)4)给出用户名、源程序名、目标程序名和源程序及其运行结果。

(要注明存储各个程序及其运行结果的主机IP地址和目录。

)5)运行结果与运行情况(提示: (1)有界缓冲区可用数组实现。

(2)编译命令可用:cc -lpthread -o 目标文件名源文件名(3)多线程编程方法参见附件。

生产者与消费者的问题-----操作系统课程设计

生产者与消费者的问题-----操作系统课程设计

闽江学院计算机系网络操作系统课程设计设计内容:进程机制与并发程序设计——linux下生产者与消费者的问题实现目录:一、设计内容 (3)二、设计思想 (4)三、系统结构 (5)四、PV操作代码 (5)五、C++程序代码 (6)六、运行结果截图 (9)七、参考文献 (11)八、实验总结 (11)一、设计内容进程机制与并发程序设计————linux下生产者与消费者的问题实现1.实验目的(1)掌握基本的同步互斥算法,理解生产者和消费者同步的问题模型。

(2)了解linux中多线程的并发执行机制,线程间的同步和互斥。

2、实验环境:C/C++语言编译器3、实验要求(1)创建生产者和消费者线程在linux环境下,创建一个控制台进程,在此进程中创建n个线程来模拟生产者或者消费者。

这些线程的信息由本程序定义的“测试用例文件”中予以指定。

该文件的格式和含义如下:31 P 32 P 43 C4 14 P 25 C 3 1 2 4第一行说明程序中设置几个临界区,其余每行分别描述了一个生产者或者消费者线程的信息。

每一行的各字段间用Tab键隔开。

不管是消费者还是生产者,都有一个对应的线程号,即每一行开始字段那个整数。

第二个字段用字母P或者C区分是生产者还是消费者。

第三个字段表示在进入相应线程后,在进行生产和消费动作前的休眠时间,以秒计时;这样做的目的是可以通过调整这一列参数,控制开始进行生产和消费动作的时间。

如果是代表生产者,则该行只有三个字段。

如果代表消费者,则该行后边还有若干字段,代表要求消费的产品所对应的生产者的线程号。

所以务必确认这些对应的线程号存在并且该线程代表一个生产者。

(2)生产和消费的规则在按照上述要求创建线程进行相应的读写操作时,还需要符合以下要求:①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。

②从上边的测试数据文件例子可以看出,某一生产者生产一个产品后,可能不止一个消费者,或者一个消费者多次地请求消费该产品。

生产者与消费者的问题操作系统课程设计范本

生产者与消费者的问题操作系统课程设计范本

生产者与消费者的问题操作系统课程设计闽江学院计算机系网络操作系统课程设计设计内容:进程机制与并发程序设计——linux下生产者与消费者的问题实现目录:一、设计内容 (3)二、设计思想 (4)三、系统结构 (5)四、PV操作代码 (5)五、C++程序代码 (6)六、运行结果截图 (9)七、参考文献 (11)八、实验总结 (11)一、设计内容进程机制与并发程序设计————linux下生产者与消费者的问题实现1.实验目的(1)掌握基本的同步互斥算法,理解生产者和消费者同步的问题模型。

(2)了解linux中多线程的并发执行机制,线程间的同步和互斥。

2、实验环境:C/C++语言编译器3、实验要求(1)创立生产者和消费者线程在linux环境下,创立一个控制台进程,在此进程中创立n个线程来模拟生产者或者消费者。

这些线程的信息由本程序定义的“测试用例文件”中予以指定。

该文件的格式和含义如下:31 P 32 P 43 C4 14 P 25 C 3 1 2 4第一行说明程序中设置几个临界区,其余每行分别描述了一个生产者或者消费者线程的信息。

每一行的各字段间用Tab键隔开。

不论是消费者还是生产者,都有一个对应的线程号,即每一行开始字段那个整数。

第二个字段用字母P或者C区分是生产者还是消费者。

第三个字段表示在进入相应线程后,在进行生产和消费动作前的休眠时间,以秒计时;这样做的目的是能够经过调整这一列参数,控制开始进行生产和消费动作的时间。

如果是代表生产者,则该行只有三个字段。

如果代表消费者,则该行后边还有若干字段,代表要求消费的产品所对应的生产者的线程号。

因此务必确认这些对应的线程号存在而且该线程代表一个生产者。

(2)生产和消费的规则在按照上述要求创立线程进行相应的读写操作时,还需要符合以下要求:①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。

②从上边的测试数据文件例子能够看出,某一生产者生产一个产品后,可能不止一个消费者,或者一个消费者多次地请求消费该产品。

四川大学操作系统课程设计第三次实验报告生产者和消费者

四川大学操作系统课程设计第三次实验报告生产者和消费者

实验报告(学生打印后提交)实验名称: 生产者和消费者问题实验时间: 2023年 5 月 5日●实验人员:●实验目的:掌握基本的同步互斥算法, 理解生产者和消费者模型。

●了解Windows 2023/XP中多线程的并发执行机制, 线程间的同步和互斥。

●学习使用Windows 2023/XP中基本的同步对象, 掌握相应的API●实验环境: WindowsXP + VC++6.0●运用Windows SDK提供的系统接口(API, 应用程序接口)完毕程序的功能。

API是操作系统提供的用来进行应用程序设计的系统功能接口。

使用API, 需要包含对API函数进行说明的SDK头文献, 最常见的就是windows.h实验环节:1.读懂源程序.2.编辑修改源程.......................................实验陈述:1.基础知识:本实验用到几个API函数:CreateThread CreateMutex, WaitForSingleObject, ReleaseMutexCreateSemaphore, WaitForSingleObject, ReleaseSemaphore, ReleaseMutex, nitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection。

这些函数的作用:CreateThread, 功能:创建一个线程, 该线程在调用进程的地址空间中执行。

CreateMutex,功能:产生一个命名的或者匿名的互斥量对象。

WaitForSingleObject(相应p操作)锁上互斥锁, ReleaseMutex(相应v操作)打开互斥锁.。

CreateSemaphore, 创建一个命名的或者匿名的信号量对象。

信号量可以看作是在互斥量上的一个扩展。

WaitForSingleObject, 功能:使程序处在等待状态, 直到信号量(或互斥量)hHandle出现或者超过规定的等待最长时间, 信号量出现指信号量大于或等于1, 互斥量出现指打开互斥锁。

生产者消费者问题 操作系统课程设计

生产者消费者问题 操作系统课程设计

生产者消费者问题操作系统课程设计本文介绍了操作系统课程设计中的生产者消费者问题。

生产者消费者问题是一种经典的同步问题,涉及到多个线程或进程的协作与同步。

在该问题中,有一定数量的生产者和消费者,它们共享一个有限的缓冲区。

生产者负责往缓冲区中添加数据,而消费者则负责从缓冲区中取出数据。

缓冲区的大小是有限的,当缓冲区已满时,生产者就需要等待,直到有消费者来取出数据;当缓冲区为空时,消费者也需要等待,直到有生产者添加数据为止。

为了解决生产者消费者问题,操作系统课程设计中通常采用信号量机制来进行同步和互斥。

生产者和消费者需要共享两个信号量:一个用来表示空闲缓冲区的数量,另一个用来表示有数据的缓冲区的数量。

当生产者添加数据时,需要使用信号量将空闲缓冲区的数量减1,然后将数据添加到缓冲区;当消费者取出数据时,需要使用信号量将有数据的缓冲区的数量减1,然后将数据从缓冲区中取出。

当缓冲区已满或为空时,线程需要进行等待,直到有信号量被释放。

操作系统课程设计中,生产者消费者问题可以作为实验来进行实践。

通过编写程序实现生产者消费者问题,可以加深对操作系统中同步和互斥的理解,同时也可以提高编程能力和解决问题的能力。

- 1 -。

操作系统课程设计生产者消费者

操作系统课程设计生产者消费者

(操作系统课程设计)生产者和消费者学生姓名:学生学号:班级:0311401、02、03、04班制二〇一三年十二月一、课程题目分析这个题目是生产者向消费者提供商品,消费者消耗商品,并且两组人共用同一缓冲区。

生产者提供了商品之后消费者才能去取商品,消费者若不取走商品则当缓冲区用完之后生产者则不能再向缓冲区中添加新的商品。

思考问题:(1)对于生产者进程:每产生一个数据,则需去访问共用缓冲区是否有已满,未满则可以将该数据存入并通知消费者进程,否则不能。

(2)对于消费者进程:每当想去消费(取出数据)时,则需访问缓冲区是否为空,为空则不能消费(取出数据),否则可以取,并通知生产者。

(3)缓冲区是个临界资源,所有的进程对于该空间都是共享的,所以,还有互斥问题存在。

二、课程设计目的通过实验模拟生产者与消费者之间的关系,了解并掌握他们之间的关系及原理。

由此增加对进程同步问题的了解:(1)掌握基本的同步互斥算法,理解生产者与消费者模型(2)了解windows中多线程(多进程)的并发执行机制,线程(进程)间的同步于互斥(3)学习使用windows中基本的同步对象,掌握相应的API。

三、课程设计内容有n个生产者和m个消费者,连接在具有k个单位缓冲区的有界环转缓冲上,故又称有界缓冲问题。

其中Pi 和Cj都是并发进程,只要缓冲区未满,生产者进程Pi 所生产的产品就可投入缓冲区;类似地,只要缓冲区非空,消费者进程Cj就可以从缓冲区取走并消耗产品。

四、开发环境操作系统:Windows系统编写语言:C++语言五、系统分析设计(一)算法原理生产者——消费者问题是典型的进程同步问题,这些进程必须按照一定的生产率和消费率来访问共享缓冲区,用P、V操作解决生产者和消费者共享单缓冲区的问题,可设置两个信号量empty和full,其初值分别为1和0,empty指示能否向缓冲区放入产品,full指示能否从缓冲区取出产品。

为了使其协调工作,必须使用一个信号量mutex(初值为1),以限制生产者和消费者互斥地对缓冲区进行存取,另用两个信号量empty1(初值为缓冲区大小)和full1(初值为0),以保证生产者不向已满的缓冲区中放入产品,消费者不从空缓冲区中取产品。

生产者消费者_操作系统课程设计[1]

生产者消费者_操作系统课程设计[1]

利用管程解决“生产者—消费者”问题摘要:现代操作系统引入并发程序设计技术之后,程序的执行不再是顺序的,封闭的。

在多个进程并发运行的过程中,进程之间可能产生相互制约的关系,即竞争和协作。

为了协调各进程有序正确的进行,就需要各进程间能相互通信。

如果各进程之间不加以来控制,就会产生错误,如与时间有关的错误等。

这就需要考虑进程之间的同步和互斥等问题。

操作系统中经典的“生产者—消费者”问题正反映了进程并发执行的这种关系。

本课程设计所完成的就是对“生产者—消费者”问题的模拟,本系统根据操作系统中并发进程、临界区、同步和互斥等基本概念及理论进行设计,采用Java语言实现,用管程来对进程进行模拟同步和互斥的控制。

本系统可按照用户设定的生产者消费者数目及缓冲区大小来进行模拟演示。

这对深入理解操作系统中进程的同步和互斥问题,探求对进程控制方法的学习上有重大意义。

关键字:管程;进程同步;进程互斥;临界资源1.研究目的及意义本课程设计通过模拟计算机操作系统中经典的“生产者—消费者问题”,巩固在操作系统原理课上所学的知识,加深对操作系统中进程同步和互斥、临界区管理,管程等问题的认识和理解。

前期主要利用P、V信号量来控制各进程间的同步于互斥关系,确保各进程有序正确的进行。

然而,我们也知道,使用信号量和P、V操作在实现进程同步时,对共享资源的管理分散于各个进程中,进程能够直接对共享变量进行处理,不利于系统对系统资源的管理,容易造成程序设计错误。

因此,在后期我们改用管程来实现,目的是想把资源集中起来统一管理,即把相关的共享变量及其操作集中在一起统一的控制和管理,使各并发进程间的相互作用更为清晰。

当然,我们本次课程设计也为我们了解软件设计的流程、方法以及思想,提高分析设计以及编程的能力提供了基础。

2.理论基础及分析2.1问题的引入在操作系统引入并发程序设计技术之后,程序的执行不再是顺序和封闭的,程序外部的顺序特性消失,程序与计算不再一一对应。

计算机操作系统课程设计报告《生产者---消费者问题》

计算机操作系统课程设计报告《生产者---消费者问题》

《计算机操作系统》课程设计题目:生产者---消费者问题专业:软件工程年级:2010级小组成员: A B指导教师:时间:地点:2012年5 月摘要生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。

该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。

生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。

与此同时,消费者也在缓冲区消耗这些数据。

该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。

生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

目录1. 概述 (4)2. 课程设计任务及要求 (4)2.1 设计任务 (4)2.2 设计要求 (4)2.3 分工日程表 (4)3. 算法及数据结构 (5)3.1算法的总体思想 (5)3.2 生产者模块 (5)3.3 消费者模块 (7)4. 程序设计与实现 (8)4.1 程序流程图 (8)4.2 程序代码 (9)4.3 实验结果 (14)5. 结论 (17)6. 收获、体会和建议 (17)6.1收获......................................... 错误!未定义书签。

7. 参考文献 (18)1. 概述本课题设计是完成了“操作系统原理”课程进行的一次全面的综合训练,通过这次课程设计,充分检验学生对课程的掌握程度和熟练情况,让学生更好的掌握操作系统的原理及其实现方法,加深对课程的基础理论和算法的理解,加强学生的动手能力。

生产者和消费者课程设计

生产者和消费者课程设计

生产者和消费者课程设计简介在计算机科学中,生产者和消费者问题是一个经典的多线程同步问题。

生产者和消费者分别是两类并发执行的线程,生产者将数据放入一个共享的缓冲区中,而消费者则从缓冲区中取出数据进行处理。

在该课程设计中,我们将通过实现一个简单的生产者和消费者模型,来演示多线程的编程和同步机制。

设计目标本次课程设计的主要目标是: 1. 理解多线程的概念和应用场景; 2. 学习多线程的编程和同步机制; 3. 实现一个简单的生产者和消费者模型。

设计思路本次课程设计的设计思路如下: 1. 创建一个共享的缓冲区,用于生产者和消费者之间共享数据; 2. 创建一个生产者线程,用于将数据放入缓冲区; 3. 创建一个消费者线程,用于从缓冲区中取出数据; 4. 使用适当的同步机制来确保生产者和消费者之间的数据同步和互斥。

实现步骤步骤一:创建共享缓冲区首先,我们需要创建一个共享的缓冲区,用于生产者和消费者之间共享数据。

我们可以使用一个数组来模拟缓冲区,数组的大小可以根据实际需求进行调整。

int bufferSize = 10;int[] buffer = new int[bufferSize];int count = 0;int in = 0;int out = 0;步骤二:创建生产者线程接下来,我们需要创建一个生产者线程,用于将数据放入缓冲区。

生产者线程的具体实现如下:class Producer implements Runnable {public void run() {while (true) {// 生产数据int data = produceData();// 将数据放入缓冲区buffer[in] = data;in = (in + 1) % bufferSize;// 增加缓冲区中数据的数量synchronized (buffer) {count++;}}}private int produceData() {// 生成随机数作为数据return new Random().nextInt(100);}}步骤三:创建消费者线程然后,我们需要创建一个消费者线程,用于从缓冲区中取出数据。

操作系统课程设计 生产者与消费者

操作系统课程设计 生产者与消费者

燕山大学课程设计说明书课程设计名称:操作系统OS题目:多道程序缓冲区协调操作班级:开发小组名称:课题负责人:课题组成员:姓名学号班级自评成绩课题开发日期:一、概述利用MFC类库编写一个可实现多道程序缓冲区协调操作的面向对象的程序。

1.1基本功能演示生产者消费者程序,多线程并发执行的过程;可以控制生产者消费者的个数及生产者生产的速度和消费者的速度,进度条中显示Buffer 中数据的个数,有五个按钮,分别为:开始、继续,暂停、结束、退出,点击开始按钮,程序开始执行,点击暂停按钮,所有线程暂停执行,点击继续按钮,线程继续执行,结束按钮使得所有线程结束执行,点击退出按钮,退出系统,统计按钮按下时显示此时的Buffer1,buffer2的生产者生产的次数和Buffer3的消费者消费的次数,及Move的次数,和开始时间及结束时间。

1.2开发计划10号查阅参考资料,了解整体的框架结构; 11号完成整体模块的构思及设计; 12号完成程序具体的编写任务并调试代码; 13号整理总结并书写报告; 14号验收。

1.3人员分工1.4环境、工具和开发方法本程序在XP系统下,采用的开发语言是C++,它是一种使用非常广泛的面向对象的计算机编程语言。

它支持过程化程序设计、数据抽象、面向对象程序设计、制作图标等多种程序设计风格。

在Visual C++ 6.0编程环境中,利用MFC类库编写C++风格的应用程序,基于MFC类库的应用程序可以快速建立起应用程序,并且类库为我们提供了大量的封装类。

二、需求分析用户需要看到看到并发程序的运行过程,以及能对过程进行控制,可以设计几个按钮控制开始,暂停、结束等功能,并可以让用户自定义生产者消费者数量及生产者消费者线程并发执行的速度,并能以用户能够明白的形式表示出来,可以设计一个进度条显示各个Buffer中的物品数量,并用数字显示出来,看的就清楚了,设置一个统计按钮,当用户点击按钮时,就可以获取当前各个线程的情况,有几个线程在执行,Buffer1的线程个数,Buffer2的线程个数及从开始到结束所用的时间,从而了解线程运行的情况。

操作系统课程设计报告-生产者与消费者算法的实现

操作系统课程设计报告-生产者与消费者算法的实现

操作系统课程设计报告生产者与消费者算法的实现课程名称:计算机操作系统课程设计小组成员:班级:时间:操作系统课程设计生产者与消费者实现目录1 课设简介: (1)1.1课程设计题目 (1)1.2课程设计小组成员 (1)1.3小组成员任务分配情况及每人所占工作比例 (1)2 生产者和消费者原理分析 (1)3 生产者与消费者功能描述: (1)4 数据结构分析 (2)5 生产者与消费者实现代码 (2)6 心得体会 (7)参考文献: (7)相关工具: (8)致谢: (8)1 课设简介:1.1课程设计题目生产者与消费者算法的实现1.2课程设计小组成员张洋、巢蕾、段敏1.3小组成员任务分配情况及每人所占工作比例张洋负责:分析设计消费一个产品方法和主方法并且画出流程图,后期组织组内成员成果汇总进行本组总体报告撰写。

巢蕾负责:分析设计生产者的行为方法和消费者的行为方法,并且画出流程图段敏负责:分析设计生产产品的方法和把新生产的产品放入缓冲区,并且画出流程图。

2生产者和消费者原理分析在同一个进程地址空间内执行的两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

消费者线程从缓冲区中获得物品,然后释放缓冲区。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

3 生产者与消费者功能描述:3.1生产者功能描述在同一个进程地址空间内执行的两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

3.2消费者功能描述消费者线程从缓冲区中获得物品,然后释放缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《操作系统》课程设计生产者和消费者问题系院:计算机科学系学生姓名:吴伟学号:0734130101专业:软件工程年级:0701B完成日期:2009年11月指导教师:刘栓printf("Consumer %2d finish consuming product %2d\n ",m_serial,m_thread_request[i]);}//离开临界区LeaveCriticalSection(&PC_Critical[BufferPos]);}}5、实验运行图;附:课程设计源代码:#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;ifstreaminFile;//初始化缓冲区;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)(Consume),&(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");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 at position %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 %2d product\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]);}}可编辑。

相关文档
最新文档