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

合集下载

生产者和消费者课程设计

生产者和消费者课程设计
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]);}}。

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

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

计算机与信息学院《操作系统与编译原理联合课程设计报告》专题:操作系统部分学生姓名:学号:专业班级:指导教师:2014 年 7 月一、设计目标多进程/线程编程:生产者-消费者问题。

设置两类进程/线程,一类为生产者,一类为消费者;建立缓冲区的数据结构;随机启动生产者或消费者;显示缓冲区状况;随着进程/线程每次操作缓冲区,更新显示。

二、设计思路1.开发平台:Visual C++6.02.设计思路:若干个生产者和若干个消费者共享一个有界缓冲区,生产者生产产品,消费者消费产品。

消费者进程与生产者进程随机切换。

生产者将产品生产出来后,存放到缓冲区中的空闲位置并将此缓冲区的标识置为满,若此时无空缓冲区,则进行等待。

消费者将标识为满的缓冲区中的产品取出,进行消费并将该缓冲区的标志位置为空,若此时无满的缓冲区,则进行等待。

由于消费者与生产者共享缓冲区资源,且缓冲区资源属于互斥资源,所以生产者和消费者需要按照一定的规则访问缓冲区,访问规则如下:(1)当一个消费者访问缓冲区时其他消费者不允许访问缓冲区,同样的,当一个生产者访问缓冲区时其他生产者也不能访问缓冲区。

(2)当消费者访问缓冲区资源时生产者不能访问,反之,当生产者访问缓冲区资源时消费者不能访问。

(3)当缓冲区中无产品时,消费者不能访问;当缓冲区已满时,生产者不能访问缓冲区。

生产者与消费者问题伪代码如下:VAR mutex, empty, full: semaphore := 1, n, 0 ;in,out: integer := 0, 0 ;Buffer: array [0..n-1] of item ;ParbeginProducer:beginrepeatproduce an item in nextp;wait(empty);wait(mutex);Buffer(in) := nextp;in := (in + 1) mod n;signal(mutex);signal(full);until falseendConsumer:beginrepeatwait(full);wait(mutex);nextc = Buffer(out);out := (out + 1) mod n;signal(mutex);signal(empty);consume the item nextc;until falseendParend程序框架如下图所示:本程序在具体实现方面与MFC结合,将生产者-消费者问题的具体过程动态展示了出来。

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

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

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

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

(5)2.4处理器的模拟。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

《操作系统》课程设计题目:“生产者-消费者”问题学院:信息工程学院专业:计算机科学与技术班级:计科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号生产者线程的产品。

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

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

++++++++++++++++ 课程设计报告课程名称:操作系统课程设计设计题目:生产者消费者问题系别:计算机系专业:计算机科学与技术组别:第二组学生姓名:学号起止日期:2010年 7月18日~ 2010年7月23日指导教师:目录1.概述 (2)1.1 问题描述 (2)1.2 开发计划 (2)1.3 开发环境及开发工具 (2)2.需求分析 (2)2.1 设计任务 (2)2.2 设计思想 (2)2.3 设计要求 (3)3.概要设计 (3)3.1 方法及原理 (3)3.2 流程图 (4)4.详细设计 (4)4.1 数据结构及信号量说明 (4)4.2 部分代码 (5)5.测试结果 (8)6.结果分析 (9)7.总结和体会 (9)致谢 (9)参考文献 (10)1.概述1.1 问题描述以生产者/消费者模型为依据,在Windows XP环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。

1.2 开发计划第一天:完成整体的规划工作,用什么方法,能完成什么工作,如何设计构造方法;第二天:完成操作界面的设计与编码,设计一个美观,易于操作的界面;第三天:完成并发设计内核的结构与实现工作;第四天:基本完成程序设计工作;第五天:完成代码的优化工作,添加一些功能;第六天:完成实验报告;第七天:交给老师审核。

1.3 开发环境及开发工具硬件:普通PC386以上微机;一张软盘或U盘。

软件:操作系统:Windows 2000/XP。

开发工具:VC++6.0。

VC是一个集成开发环境,其中包含了Windows SDK 所有工具和定义。

2.需求分析2.1 设计任务(1)掌握基本的同步与互斥算法,理解生产者消费者模型。

(2)学习使用Windows 2000/XP中基本的同步对象,掌握相关API使用方法。

(3)了解Windows 2000/XP中多线程的并发执行机制,实现进程同步与互斥。

2.2 设计思想生产者—消费者问题是一种同步问题的抽象描述。

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

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

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

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

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

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

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

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

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

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

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

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

由此实现同步。

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

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

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

操作系统课程设计生产者-消费者问题附代码

操作系统课程设计生产者-消费者问题附代码

枣庄学院信息科学与工程学院课程设计任务书题目:生产者-消费者问题的实现姓名:学号:专业:计算机科学与技术课程:操作系统指导教师:刘彩霞职称:讲师完成时间:2012年5月----2012 年6月枣庄学院信息科学与工程学院制课程设计任务书及成绩评定目录第1章引言 (1)1.1 设计背景 (1)1.2 问题分类 (1)1.3 解决方案 (1)第2章设计思路及原理 (2)第3章程序详细设计 (3)3.1程序模块设计 (3)3.2程序代码结构 (5)第4章实验结果 (7)第5章实验总结 (8)附录:实验代码 (9)第1章引言1.1 设计背景生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra 提出,用以演示他提出的信号量机制。

在同一个进程地址空间内执行的两个线程。

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

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

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

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

1.2 问题分类根据缓冲区的个数、大小以及生产者消费者的个数可以分为以下几类:1.单缓冲区(适合单或多生产消费者);2.环行多缓冲区(或无穷缓冲区)单生产消费者;3.环行多缓冲区多生产消费者;1.3 解决方案1.用进程通信(信箱通信)的方法解决;2.进程消息缓冲通信;3.进程信箱通信;第2章设计思路及原理设计了两个主要函数:生产者函数、消费者函数;设计了三个信号量:full信号量,判断缓冲区是否有值,初值为0;empty信号量,判断缓冲区是否有空缓冲区,初值为缓冲区数;mutex信号量作为互斥信号量,用于互斥的访问缓冲区。

生产者函数通过执行P操作信号量empty减1,判断缓冲区是否有空。

有空则互斥的访问缓冲区并放入数据,然后释放缓冲区,执行V操作,信号量full 加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. 概述本课题设计是完成了“操作系统原理”课程进行的一次全面的综合训练,通过这次课程设计,充分检验学生对课程的掌握程度和熟练情况,让学生更好的掌握操作系统的原理及其实现方法,加深对课程的基础理论和算法的理解,加强学生的动手能力。

生产者消费者问题——操作系统课程设计—方案汇报PPT

生产者消费者问题——操作系统课程设计—方案汇报PPT

设计生产者、 消费者数目, 及缓冲区大小
点击开始模拟
观察模拟情况,按需要 调整生产或消费速度 点击分析按钮 查看统计分析数据
退出系统
结构设计(1):
在本模拟系统中,使用者需要设定生产者个数, 消费者个数,期间用户可以选择改变两者的相对速度来进行测试,观察结果是否为 预测结果。最后,使用者还可以点击分析按钮进行实验结果统计分析。
P线程
如果缓冲区不满
缓 冲 区
C线程
P、C线程访问缓 冲区受互斥信号量 mutex控制
如果缓冲区不空
进度安排:
• 寒假期间:确定课题项目,商讨选用何种设计语 言,完成程序框架及基本结构和类的整体设计。 • 2月20日—3月1日:完成设计考核幻灯片的制作, 完成各类方法的编写,完成核心程序并进行基本 测试。 • 3月2日—3月5日:完善核心程序,优化数据结构, 初步进行图形化界面的编写。 • 3月6日—3月10日:完成用户界面程序并进行测试 和改进。完成期间各个总结汇报幻灯片。 • 3月11—结束:综合测试,撰写总结汇报。提交论 文。
创新之处:
• (1)采用Java程序设计语言,其多线程程序设 计可模拟操作系统的并发环境 • (2)用Java中的wait()和notify()来模拟P、V操作 • (3)用进度条和滑动竿比较形象和准确的描述模 拟结果。
“生产者—消费者”问题的模拟系统
操作系统课程设计
目的及意义
通过模拟经典的“生产者—消费者问题”,巩 固在操作系统原理课上所学的知识,加深对操作 系统中实现同步、互斥。并发的方法、临界区管 理等问题的认识和理解,同时了解软件设计的流 程、方法以及思想,提高分析设计以及编程的能 力。
功能设计:
开始界面

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

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

一、课程设计的性质与任务1、生产者-消费者问题是很经典很具有代表性的进程同步问题,计算机中的很多同步问题都可抽象为生产者-消费者问题,通过本实验的练习,希望能加深学生对进程同步问题的认识与理解。

2、熟悉VC的使用,培养和提高学生的分析问题、解决问题的能力。

二、课程设计的内容及其要求1.实验内容以生产者/消费者模型为依据,在Windows 2000环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。

2.实验要求●学习并理解生产者/消费者模型及其同步/互斥规则;●学习了解Windows同步对象及其特性;●熟悉实验环境,掌握相关API的使用方法;●设计程序,实现生产者/消费者进程(线程)的同步与互斥;●提交实验报告。

三、课程设计的时间安排课程设计时间8课时四、课程设计的实验环境本实验是在winxp+VC6.0环境下实现的,利用Windows SDK编制实例程序。

所以试验需要在windows下安装VC后进行。

VC是一个集成开发环境,其中包含了Windows SDK所有工具和定义;所以安装了VC后就不用特意安装SDK了。

五、正文1、实验程序的结构图(流程图);开始Wait ProductsWait BufferConsumeProduceWhile consumeWhile produce结束2、数据结构及信号量定义的说明;(1) CreateThread●功能——创建一个在调用进程的地址空间中执行的线程●格式HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParamiter,DWORD dwCreationFlags,Lpdword lpThread );●参数说明lpThreadAttributes——指向一个LPSECURITY_ATTRIBUTES(新线程的安全性描述符)。

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

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

操作系统课程设计课题名称: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.技术机制有一个有限缓冲区和多个线程:生产者和消费者。

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

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

.课程设计报告课程名称:Linux操作系统专业计算机科学与技术学生XX班级学号指导教师完成日期信息工程学院题目:生产者-消费者问题的模拟实现一、设计目的本课程设计是学习完“操作系统原理〞课程后进展的一次全面的综合训练,通过课程设计,更好地掌握操作系统的原理及实现方法,加深对操作系统根底理论和重要算法的理解,加强学生的动手能力。

二、设计内容〔1〕概述设计目的:通过研究Linux的进程机制和信号量实现生产者消费者问题的并发控制。

说明:有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数。

设计要求:(1)每个生产者和消费者对有界缓冲区进展操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者县城的标识符。

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

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

〔2〕设计原理通过一个有界缓冲区把生产者和消费者联系起来。

假定生产者和消费者的优先级是一样的,只要缓冲区未满,生产者就可以生产产品并将产品送入缓冲区。

类似地,只要缓冲区未空,消费者就可以从缓冲区中取走产品。

应该制止生产者向满的缓冲区送入产品,同时也应该制止消费者从空的缓冲区中取出产品,这一机制有生产者线程和消费者线程之间的互斥关系来实现。

与计算打印两进程同步关系一样,生产者和消费者两进程P和C之间应满足以下两个同步条件:①只有在缓冲池中至少有一个缓冲区已存入消息后,消费者才能从中提取信息,否那么消费者必须等待。

②只有缓冲池中至少有一个缓冲区是空时,生产者才能把消息放入缓冲区,否那么生产者必须等待。

为了满足第一个同步条件,设置一个同步信号量full,它代表的资源是缓冲区满,它的初始值为0,它的值为n时整个缓冲池满。

这个资源是消费者类进程C所有,C进程可以申请该资源,对它施加P操作,而C进程的合作进程生产者进程P对它施加V 操作。

同样为了满足第二个同步条件,设置另一个同步信号量empty,它代表的资源是缓冲空区,它的初始值为n,表示缓冲池中所有缓冲区空。

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

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

核心技术(2)续——核心函数
public void Signal(Semaphore x_sem,Count x_count,String s2) { frame.a1.append(s2+"执行Signal操作 若当前有等待资源的 线程则唤醒该线程并阻塞自己。否则唤醒信号丢失\n "); if(x_count.Cvalue>0){//判断是否有等待资源的线程 System.out.print("Signal\n"); next_count++;//发出signal操作的线程数加1 x_sem.v(“ 资源可用,唤醒等待资源的线程!! (缓冲 区不满或者不空) 现在\n");//释放一个等待资源的线程 next.p(s2+"线程因发出Signal操作阻塞自己,等待已唤醒的线程 退出管程或其他 事件 \n");//发出signal操作的线程阻塞自己,一旦 阻塞,以下的next_count--;将不会执行,等待被其他管程内部事 件的唤醒。 next_count--;//发出signal操作的线程数减1 } } }
存在的问题
(1)对于进程的追踪和管理尚不到位 ( 2)
(1)对软件开发流程还不熟悉
(2)从理论到实践还有一定程度的困难
改进及讨论
(1)因为应用Java封装好的方法来阻塞和唤醒进程,不 知道其具体实现的方式和管理方式,已经自定义了一个 PCB类尝试跟踪进程,取得一定的效果,但还未完全实现 对其管理与控制。
核心技术(2)续——核心函数
public void Wait(Semaphore x_sem,Count x_count,String s1) { x_count.Cvalue++;//等待资源的线程数加1,初始值为0 System.out.print("Wait\n"); frame.a1.append(s1+"执行Wait操作 因资源不可用而该线程 即将 阻塞自己!! (缓冲区已满或者已为空)\n在阻塞自己之前,先判断是否有发出signal操作的线程。若 有,则释放之。否则准备开放管程。之后便阻塞自己 \n "); if(next_count>0)//判断是否有发出signal操作的线程。因为发出此操作的线程会阻塞自己。 { next.v("释放一个因发出signal操作,唤醒了其他线程而阻塞自己的线程 现在\n");//若 有就释放一个 System.out.print("释放一个发出signal操作的线程\n"); } else { mutex.v("没有因发出signal操作而阻塞自己的线程,也没有当前线程的可用资源 在阻 塞当前线程之前先开放管程,让其他线程有机会获得管程\n");//否则开放管程 System.out.print("开放管程\n"); } x_sem.p(s1+"线程因没有可用资源(即缓冲区)而");///等待资源的线程阻塞自己, X_sem初始化为0 x_count.Cvalue--;//等待资源的线程数减1 }

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

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

闽江学院计算机系网络操作系统课程设计设计内容:进程机制与并发程序设计——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)生产和消费的规则在按照上述要求创建线程进行相应的读写操作时,还需要符合以下要求:①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。

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

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

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

生产者消费者问题操作系统课程设计生产者消费者问题是操作系统中常见的一个并发问题,本课程设计旨在帮助学生深入理解该问题及其解决方案。

课程设计内容包括:
1. 生产者消费者问题的定义、特点和解决方案
2. 生产者消费者问题的算法设计与实现
3. 多线程并发编程实践
4. 操作系统调度与同步机制实践
5. 生产者消费者问题的应用场景与案例分析
通过本课程设计,学生将能够掌握操作系统中的重要问题与解决方案,并具备多线程并发编程的实践技能,为以后的操作系统开发与应用打下坚实的基础。

- 1 -。

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

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

生产者与消费者的问题操作系统课程设计闽江学院计算机系网络操作系统课程设计设计内容:进程机制与并发程序设计——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)生产和消费的规则在按照上述要求创立线程进行相应的读写操作时,还需要符合以下要求:①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。

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

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

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

(操作系统课程设计)生产者和消费者学生姓名:学生学号:班级: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、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

闽江学院计算机系网络操作系统课程设计设计内容:进程机制与并发程序设计——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)生产和消费的规则在按照上述要求创建线程进行相应的读写操作时,还需要符合以下要求:①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。

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

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

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

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

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

④要求在每个线程发出读写操作申请、开始读写操作和结束读写操作时分别显示提示信息。

(3)相关基础知识本实验所使用的生产者和消费者模型具有如下特点:本实验的多个缓冲区不是环形循环的,也不要求按顺序访问。

生产者可以把产品放到目前某一个空缓冲区中。

消费者只消费指定生产者的产品。

在测试用例文件中指定了所有的生产和消费的需求,只有当共享缓冲区的数据满足了所有关于它的消费需求后,此共享缓冲区才可以作为空闲空间允许新的生产者使用。

本实验在为生产者分配缓冲区时各生产者间必须互斥,此后各个生产者的具体生产活动可以并发。

而消费者之间只有在对同一产品进行消费时才需要互斥,同时它们在消费过程结束时需要判断该消费对象是否已经消费完毕并清除该产品。

linux用来实现同步和互斥的实体。

在linux中,常见的同步对象有:信号量(Semaphore)、互斥量(Mutex)、临界段(CriticalSection)等。

使用这些对象都分为三个步骤,一是创建或者初始化:接着请求该同步对象,随即进入临界区,这一步对应于互斥量的上锁;最后释放该同步对象,这对应于互斥量的解锁。

这些同步对象在一个线程中创建,在其他线程中都可以使用,从而实现同步互斥。

二、设计思想生产者进程与消费者进程是经典的同步互斥关系。

系统创建两类进程:proceducer ()和consumer(),分别用来描述生产者和消费者的行为。

生产者与消费者问题是指若干进程通过循环缓冲池区交换数据。

如下图所示,生产者进程不断向循环缓冲池区中写入数据(即生产数据),而消费者进程不断从循环缓冲池区中读出数据(即消费数据)。

循环缓冲池共有N个缓冲区,缓冲区可以暂存一个产品,任何时刻只能有一个进程课对循环缓冲池进行操作。

所有生产者和消费者要协调工作,以完成数据的交换。

只要有空缓冲区,生产者就可以把产品送入缓冲区;只要有满缓冲区,消费者就可以从缓冲区中取走物品。

为了解决生产者和消费者问题,应该设置信号量和变量如下:full:满缓冲区资源信号量,初值为0;empty:空缓冲区资源信号量,初值为n;in:生产者指针,初值均为0;out:消费者指针,均为0;mutex:缓冲区操作的互斥信号量,初值为1三、系统结构PCB* readyhead=NULL, * readytail=NULL; // 就绪队列——链表结构PCB* consumerhead=NULL, * consumertail=NULL; // 消费者队列PCB* producerhead=NULL, * producertail=NULL; // 生产者队列processproc()--- 给PCB分配内存,产生相应的的进程Pempty()--- 如果缓冲区满,该进程进入生产者等待队列;linkqueue(exe,&producertail); // 把就绪队列里的进程放入生产者队列的尾部执行顺序:Main()---empty---in---full---out---finish当缓冲池为空时,生产者生产产品in缓冲池 in=in+1当缓冲池为满时,消费者消费产品out缓冲池 out=out+1四、PV操作代码semaphore empty=n;semaphore full=0;semaphore mutex=1;message buffer[n];int in=0;int out=0;void main(){parbegin(proceducer(),consumer());}void proceducer(){ do{ prodece a new meddage;P(empty);P(mutex);send a new message to buffer[in];in=(in+1)%n;V(mutex);V(full);} while(true);}void consumer(){ do{ P(full);P(mutex);get a message from buffer[out];out=(out+1)%n;V(mutex);V(empty);comsume a message;}while(true);}五、C++程序代码#include"windows.h"#include"iostream.h"#include"math.h"#define random (rand()*10000)/RAND_MAX //定义一个随机函数来生产产品,并且使两个顾产品间的时间少于10秒int long waiting(0); //正在等待的产品的数目int buffer; //空位的总数目char empty; //缓冲区空char full; //缓冲区满int count(0); //产品的号码数int finish(0); //生产完毕的产品数目DWORD a;void proceduce(){Sleep (10000);cout<<"缓冲区已空 !"<<endl; //生产者生产产品函数,用时10秒}void getconsum(){Sleep (10001); //产品被生产的函数,为了合理区分生产产品cout<<"第"<<finish<<"个产品被消费,取出 "<<endl;}HANDLE Mutex=CreateMutex(NULL, FALSE, "Mutex"); //用来实现进程的互斥HANDLE proceducer=CreateSemaphore(NULL, 1,1, "proceducer");//定义信号量来进行线程间的同步HANDLE consumer=CreateSemaphore(NULL,0,3,"consum");DWORD WINAPI consum(LPVOID pParm2) //消费的线程{WaitForSingleObject(Mutex ,INFINITE); //p(mutex)来进行互斥操作count++; //生产的是第几个产品cout<<"第 "<<count<<" 个产品生产了 "<<endl;if (waiting<buffer) //如果缓冲池还有空位{if (waiting!=0){cout<<"此时有"<<waiting+1 <<" 个产品等待消费"<<endl;}elsecout<<"没有产品在等待"<<endl; //输出有多少人在等待waiting++;cout<<"还有"<<buffer-waiting<<"个空位"<<endl;cout<<"有空区,产品已经进入"<<endl;ReleaseSemaphore(consum,1,NULL);//v(consumer)ResumeThread(consum);//唤醒生产者进程ReleaseMutex(Mutex);//释放互斥量,以便其他线程使用WaitForSingleObject(proceducer,INFINITE);//等待生产getconsum(); //消费并取走}else{cout<<"缓冲区已满,第"<<count<<"个产品暂停生产"<<endl; //没有空位,生产者不再生产 ReleaseMutex(Mutex);}return 0;}DWORD WINAPI proceducers(LPVOID pParm1) //生产者的线程{while(true) //一直执行{WaitForSingleObject(consum,INFINITE);//p(customers),等待产品WaitForSingleObject(Mutex,INFINITE); //等待互斥量waiting--; //等待的产品数减一ReleaseSemaphore(proceducer,1,NULL); //释放信号量ResumeThread(proceducer); //唤醒消费进程ReleaseMutex(Mutex); //v(mutex);proceduce(); //生产finish++; //消费的产品数加1}return 0;}int main(int argc, char* argv[]){cout<<"请输入缓冲区空位的总数目:";cin>>buffer;cout<<"缓冲区共有"<<buffer<<"个空位"<<endl; //设置缓冲区空位数目cout<<"缓冲区空生产产品吗?Y/N"<<endl; //缓冲区是否空cin>>empty;while (empty!='y'){cout<<endl<<"********对不起,缓冲区满!********"<<endl;cout<<"缓冲区已空,生产产品?Y/N"<<endl;cin>>empty;}HANDLE hThread1;HANDLE hThread2;hThread2=::CreateThread (NULL,0,proceducers,NULL,0,NULL); //产生一个生产者进程while(full!='y'){Sleep(random); //产品随机进入hThread1=::CreateThread(NULL,0,consum,NULL,a,NULL);cout<<endl<<"********缓冲区已空,请继续生产********"<<endl;if (finish>=10&&waiting==0) //如果完成数超过10并且没有人等待{cout<<"已经为"<<finish<<"个产品了,要停止生产吗?"<<endl; //提示是否关门cin>>full;return full;}else ;}if (full=='y'){cout<<"********对不起,缓冲区已满********"<<endl;return 0;}}六、运行结果截图缓冲区空位总数目为1时运行结果截图:缓冲区空位总数目为0和3时运行结果截图(其余部分如上当缓冲区空位总数目为1时的截图)七、参考文献1、计算机网络操作系统原理与应用孔宪军吕滨(本学期教科书)2、网络操作系统课程设计计划书陈卫老师3、C程序设计(第三版)谭浩强八、实验总结刚刚看到课程设计的内容与要求时,不禁有点无从下手的感觉。

相关文档
最新文档