操作系统课程设计——生产者消费者问题
操作系统_生产者和消费者
《操作系统》课程设计生产者和消费者的问题学院:计算机学院学生姓名:屈杨学号: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的状态。
操作系统课程设计生产者消费者
生产者消费者问题 (Producer-consumer problem) , 也称有限缓冲问题 (Bounded-buffer problem),是一个多线程同步问题的经典案例。 该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”— —在实际运行时会发生的问题。 生产者的主要作用是生成一定量的数据放到缓冲区中, 然后 重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者 不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。 要解决该问题,就必须让生产者在缓冲区满时休眠(或者放弃数据),等到下次消费者 消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让 消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采 用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容 易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能 被推广到多个生产者和消费者的情形。
5
pthread_mutex_lock(&lock); while (q->num == 0) { pthread_cond_wait(&empty, &lock); } sem_wait(&product_number); q->front = (q->front + 1) % NUM; char c = q->productc[q->front]; q->productc[q->front] = ' '; q->num--; printf("消费者 1 显示内容: %c\n", c); printf("产品数量:%d\n", q->num); sem_post(&blank_number); if (q->num == NUM - 1) { pthread_cond_signal(&full); } pthread_mutex_unlock(&lock); sleep(rand() % 2); } } void *consumer2(void *arg) { struct P_Queue *q; q = (struct P_Queue *) arg; while (1) { pthread_mutex_lock(&lock); while (q->num == 0) { pthread_cond_wait(&empty, &lock); } sem_wait(&product_number); q->front = (q->front + 1) % NUM; char c = q->productc[q->front]; char d = 0; if(c>=65 && c<=90) { d = c+32;} else { d = c-32;} q->productc[q->front] = ' '; q->num--; printf("消费者 2 更改大小写:%c---%c\n", c,d); printf("产品数量:%d\n", q->num); sem_post(&blank_number); if (q->num == NUM - 1) { pthread_cond_signal(&full); }
操作系统课程设计“生产者-消费者”问题
《操作系统》课程设计题目:“生产者-消费者”问题学院:信息工程学院专业:计算机科学与技术班级:计科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,来分别代表消费者的可用资源数、生产者的可用资源数、缓冲区是否可用。
计算机操作系统课程设计报告《生产者---消费者问题》
计算机操作系统课程设计报告《生产者---消费者问题》《计算机操作系统》课程设计题目:生产者---消费者问题专业:软件工程年级: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
设计生产者、 消费者数目, 及缓冲区大小
点击开始模拟
观察模拟情况,按需要 调整生产或消费速度 点击分析按钮 查看统计分析数据
退出系统
结构设计(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)用进度条和滑动竿比较形象和准确的描述模 拟结果。
“生产者—消费者”问题的模拟系统
操作系统课程设计
目的及意义
通过模拟经典的“生产者—消费者问题”,巩 固在操作系统原理课上所学的知识,加深对操作 系统中实现同步、互斥。并发的方法、临界区管 理等问题的认识和理解,同时了解软件设计的流 程、方法以及思想,提高分析设计以及编程的能 力。
功能设计:
开始界面
操作系统生产者与消费者课程设计
操作系统课程设计课题名称: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,然后将数据添加到缓冲区;当消费者取出数据时,需要使用信号量将有数据的缓冲区的数量减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]
利用管程解决“生产者—消费者”问题摘要:现代操作系统引入并发程序设计技术之后,程序的执行不再是顺序的,封闭的。
在多个进程并发运行的过程中,进程之间可能产生相互制约的关系,即竞争和协作。
为了协调各进程有序正确的进行,就需要各进程间能相互通信。
如果各进程之间不加以来控制,就会产生错误,如与时间有关的错误等。
这就需要考虑进程之间的同步和互斥等问题。
操作系统中经典的“生产者—消费者”问题正反映了进程并发执行的这种关系。
本课程设计所完成的就是对“生产者—消费者”问题的模拟,本系统根据操作系统中并发进程、临界区、同步和互斥等基本概念及理论进行设计,采用Java语言实现,用管程来对进程进行模拟同步和互斥的控制。
本系统可按照用户设定的生产者消费者数目及缓冲区大小来进行模拟演示。
这对深入理解操作系统中进程的同步和互斥问题,探求对进程控制方法的学习上有重大意义。
关键字:管程;进程同步;进程互斥;临界资源1.研究目的及意义本课程设计通过模拟计算机操作系统中经典的“生产者—消费者问题”,巩固在操作系统原理课上所学的知识,加深对操作系统中进程同步和互斥、临界区管理,管程等问题的认识和理解。
前期主要利用P、V信号量来控制各进程间的同步于互斥关系,确保各进程有序正确的进行。
然而,我们也知道,使用信号量和P、V操作在实现进程同步时,对共享资源的管理分散于各个进程中,进程能够直接对共享变量进行处理,不利于系统对系统资源的管理,容易造成程序设计错误。
因此,在后期我们改用管程来实现,目的是想把资源集中起来统一管理,即把相关的共享变量及其操作集中在一起统一的控制和管理,使各并发进程间的相互作用更为清晰。
当然,我们本次课程设计也为我们了解软件设计的流程、方法以及思想,提高分析设计以及编程的能力提供了基础。
2.理论基础及分析2.1问题的引入在操作系统引入并发程序设计技术之后,程序的执行不再是顺序和封闭的,程序外部的顺序特性消失,程序与计算不再一一对应。
操作系统实验报告生产者消费者问题
《操作系统课程设计》实验报告生产者消费者问题2013年12 月25 日一设计目标运用条件变量和互斥锁原理实现线程同步问题,解决生产者消费者问题1.1 背景知识说明在Linux环境下需要使用POSIX库进行设计实现,POSIX是Portable Operating System Interface of Unix的缩写。
由IEEE(Institute of Electrical and Electronic Engineering)开发,由ANSI和ISO 标准化。
POSIX的诞生和Unix的发展是密不可分的,Unix于70年代诞生于贝尔实验室,并于80年代向美各大高校分发V7版的源码以做研究。
加利福尼亚大学伯克利分校在V7的基础上开发了BSD Unix。
后来很多商业厂家意识到Unix的价值也纷纷以贝尔实验室的System V或BSD 为基础来开发自己的Unix,较著名的有Sun OS,AIX,VMS。
文档收集自网络,仅用于个人学习基于posix的线程标准库是pthreadPOSIX线程(POSIX Thread),简称Pthread,是线程的POSIX 标准。
该标准定义了创建和操纵线程的一整套API。
在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthread作为操作系统的线程。
Windows操作系统也有其移植版pthread-win32。
文档收集自网络,仅用于个人学习Pthreads定义了一套C语言的类型、函数与常量,它以pthread.h头文件和一个线程库实现。
1.2 原理在同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
操作系统生产者与消费者课程设计
《操作系统》课程设计生产者和消费者问题系院:计算机科学系学生姓名:吴伟学号:01专业:软件工程年级:0701B完成日期:2009年11月指导教师:刘栓二、课程设计的内容及其要求1.实验内容以生产者/消费者模型为依据,在Windows 2000环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
2.实验要求学习并理解生产者/消费者模型及其同步/互斥规则;学习了解Windows同步对象及其特性;熟悉实验环境,掌握相关API的使用方法;设计程序,实现生产者/消费者进程(线程)的同步与互斥;提交实验报告。
五、正文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(新线程的安全性描述符)。
dwStackSize——定义原始堆栈大小。
lpStartAddress——指向使用LPTHRAED_START_ROUTINE类型定义的函数。
lpParamiter——定义一个给进程传递参数的指针。
dwCreationFlags——定义控制线程创建的附加标志。
lpThread——保存线程标志符(32位)(2) CreateMutex功能——创建一个命名或匿名的互斥量对象格式HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName);参数说明lpMutexAttributes——必须取值NULL。
操作系统-生产者消费者问题
生产者消费者问题当缓冲区为空时,in与out在数值上相等;当缓冲区满时,in与out在数值上也相等。
那么,这就产生了不能判断的情况,不能通过in与out在数值上是否相等来判断缓冲区是否为空或者是否为满,本质上是循环队列产生的问题。
这种问题有很多解决方案,除了牺牲一个位置以外,增加一个标识、增加计数器或者用特殊值来表示等等都是可以的。
○ 方案一:增加计数器count1、操作count初始值为0;当生产者向缓冲区增加一项时,count自增1;当消费者从缓冲区移走一项时,count自减12、代码1)生产者while (true){while (count == BUFFER_SIZE); /* do nothing -- no free buffers */buffer[in] = nextProduced;in = (in + 1) % BUFFER_SIZE;count ++;}2)消费者while (true){while(count == 0); /*do nothing -- nothing to consume */nextConsumed = buffer[out];out = (out + 1) % BUFFER_SIZE;count --;}3、问题当生产者和消费者的代码并发执行时可能不能正确运行。
○ 方案二:利用flag作为标识1、操作使用布尔类型的变量full来表示缓冲区是否已满,当值为true表示缓冲区已满,当值为false表示缓冲区未满;初始值为false,在生产者向缓冲区中增加项时进行检查2、代码初始化:bool full = false;1)生产者while (true){while (full); /* do nothing -- no free buffers */buffer[in] = nextProduced;in = (in + 1) % BUFFER_SIZE;if (in == out){full = true;}}2)消费者while (true){while(in == out && !full); /*do nothing -- nothing to consume */nextConsumed = buffer[out];out = (out + 1) % BUFFER_SIZE;if (full){full = false;}}。
操作系统课程设计-管程的实现(生产者消费者问题)
操作系统课程设计2、管程的实现(生产者消费者问题)1.设计背景:管程是一种高级抽象数据类型,它支持在它的函数中隐含互斥操作。
结合条件变量和其他一些低级通信原语,管程可以解决许多仅用低级原语不能解决的同步问题。
例如,本实验中利用管程提供一个不会发生死锁的生产者消费者问题就是利用管程的很好的例子。
管程封装了并发进程或线程要互斥执行的函数。
为了让这些并发进程或线程在管程内互斥的执行,管程的实现必须隐含的具有锁或二值信号量。
如果没有条件变量,管程就不会有很有用,条件变量提供了一种对管程内并发协作进程的同步机制。
条件变量代表了管程中一些并发进程或线程可能要等待的条件。
一个条件变量管理着管程内的一个等待队列。
如果管程内某个进程或线程发现其执行条件为假,则该进程或线程就会被条件变量挂入管程内等待该条件的队列。
如果管程内另外的进程或线程满足了这个条件,则它会通过条件变量再次唤醒等待该条件的进程或线程,从而避免了死锁的产生。
所以,一个条件变量C应具有两种操作 C.wait()和C.signal()。
当管程内同时出现唤醒者和被唤醒者时,由于要求管程内的进程或线程必须互斥执行,因此就出现了两种样式的条件变量:Mesa Style(signal-and-continue): 唤醒者进程或线程继续执行,被唤醒者进程或线程等到唤醒者进程或线程阻塞或离开管程后再执行。
Hoare Style(signal-and-wait): 被唤醒者进程或线程立即执行,唤醒者进程或线程阻塞,直道被唤醒者阻塞或离开管程后再执行。
我们实验所做的就是在原来mesa样式的基础上进行Hoare样式的改进;这种样式也是我们实验中需要实现的样式。
2.设计目标验证并分析Nachos中Bridge管程是否能够正确的解决单行桥双向过桥问题。
定义和实现Hoare样式的条件变量Condition_H类利用Hoare样式的条件变量Condition_H,实现Ring类中定义的各个方法,使用Ring管程解决生产者/消费者问题。
操作系统课程设计-生产者消费者问题linux
#include<stdio.h>#include<pthread.h>#define MAX 30#define BUFFER_SIZE 20pthread_mutex_t the_mutex,the_main,the_p;pthread_cond_t condc,condp;int buffer[BUFFER_SIZE];int in=0;int out=0;int counter=0;int flg[30]={0};int k=0;int p=0;void *producer1(void* s){pthread_mutex_lock(&the_main);pthread_mutex_unlock(&the_main);int proid=(int)s;int i;for(i=1;i<=MAX;i++){pthread_mutex_lock(&the_mutex);while(counter==BUFFER_SIZE){printf("%d号生产者wait...\n",proid);pthread_cond_wait(&condp,&the_mutex);printf("%d号生产者唤醒...\n",proid);}buffer[in]=1;printf("%d号生产者生产1放入%d中\n",proid,in);in=(in+1)%BUFFER_SIZE;counter++;pthread_cond_signal(&condc);pthread_mutex_unlock(&the_mutex);}pthread_mutex_lock(&the_p);p++;printf("%d号生产者线程结束\n",proid);pthread_mutex_unlock(&the_p);return 0;}void *consumer1(void* s){pthread_mutex_lock(&the_main);pthread_mutex_unlock(&the_main);int conid=(int)s;int j=1;int k=0;while(1){pthread_mutex_lock(&the_mutex);if(p==30&&counter==0){pthread_mutex_unlock(&the_mutex);break;}// printf("p=%d counter=%d\n",p,counter);while(counter==0){if(p==30&&counter==0){pthread_mutex_unlock(&the_mutex);break;}printf(" %d号消费者wait...\n",conid); pthread_cond_wait(&condc,&the_mutex);printf("%d号消费者唤醒...\n",conid);}if(buffer[out]==4){printf("%d号消费者在%d处消费%d counter=%d p=%d\n",conid,out);buffer[out]=0;out=(out+1)%BUFFER_SIZE;counter--;pthread_cond_signal(&condp);}if(buffer[out]==1&&flg[conid]==0){flg[conid]=1;printf("%d号消费者在%d处消费%d counter=%d p=%d\n",conid,out);for(j=1;j<=29;j=j+2)if(flg[j]==1)k++;if(k==15){k=0;for(j=1;j<=29;j++)flg[j]=0;buffer[out]=0;out=(out+1)%BUFFER_SIZE;counter--;pthread_cond_signal(&condp);}elsek=0;}else{pthread_cond_signal(&condc);}pthread_mutex_unlock(&the_mutex);}printf("%d消费者线程结束\n",conid);pthread_exit(0);}int main(int argc,char **argv){int j;pthread_t pro[31],con[31];pthread_mutex_init(&the_mutex,0);pthread_mutex_init(&the_main,0);pthread_cond_init(&condc,0);pthread_cond_init(&condp,0);pthread_mutex_lock(&the_main);for(j=1;j<=10;j=j+2){pthread_create(&pro[j],0,producer1,(void*)j);pthread_create(&con[j],0,consumer1,(void*)j);}printf("线程创建完成\n");pthread_mutex_unlock(&the_main);for(j=1;j<=30;j++){pthread_join(con[j],0);}printf("消费者线程结束\n");pthread_mutex_destroy(&the_main);pthread_cond_destroy(&condc);pthread_cond_destroy(&condp);pthread_mutex_destroy(&the_mutex);。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机与信息学院
《操作系统与编译原理联合课程设计报告》
专题:操作系统部分
学生姓名:
学号:
专业班级:
指导教师:
2014 年 7 月
一、设计目标
多进程/线程编程:生产者-消费者问题。
设置两类进程/线程,一类为生产者,一类为消费者;建立缓冲区的数据结构;随机启动生产者或消费者;显示缓冲区状况;随着进程/线程每次操作缓冲区,更新显示。
二、设计思路
1.开发平台:Visual C++6.0
2.设计思路:
若干个生产者和若干个消费者共享一个有界缓冲区,生产者生产产品,消费者消费产品。
消费者进程与生产者进程随机切换。
生产者将产品生产出来后,存放到缓冲区中的空闲位置并将此缓冲区的标识置为满,若此时无空缓冲区,则进行等待。
消费者将标识为满的缓冲区中的产品取出,进行消费并将该缓冲区的标志位置为空,若此时无满的缓冲区,则进行等待。
由于消费者与生产者共享缓冲区资源,且缓冲区资源属于互斥资源,所以生产者和消费者需要按照一定的规则访问缓冲区,访问规则如下:
(1)当一个消费者访问缓冲区时其他消费者不允许访问缓冲区,同样的,当一个生产者访问缓冲区时其他生产者也不能访问缓冲区。
(2)当消费者访问缓冲区资源时生产者不能访问,反之,当生产者访问缓冲区资源时消费者不能访问。
(3)当缓冲区中无产品时,消费者不能访问;当缓冲区已满时,生产者不能访问缓冲区。
生产者与消费者问题伪代码如下:
VAR mutex, empty, full: semaphore := 1, n, 0 ;
in,out: integer := 0, 0 ;
Buffer: array [0..n-1] of item ;
Parbegin
Producer:
begin
repeat
produce an item in nextp;
wait(empty);
wait(mutex);
Buffer(in) := nextp;
in := (in + 1) mod n;
signal(mutex);
signal(full);
until false
end
Consumer:
begin
repeat
wait(full);
wait(mutex);
nextc = Buffer(out);
out := (out + 1) mod n;
signal(mutex);
signal(empty);
consume the item nextc;
until false
end
Parend
程序框架如下图所示:
本程序在具体实现方面与MFC结合,将生产者-消费者问题的具体过程动态展示了出来。
以下为界面的设计:
(1)界面拥有三个可输入的编辑框,分别对应着生产者数量、消费者数量以及缓冲区
大小。
(2)界面中有两个按钮,分别为“开始”和“停止”。
“开始”按钮用于获取生产值数量、消费者数量以及缓冲区大小,用于初始化以上三个量,并启动进程。
“停止”按钮用于停止程序的运行。
(3)三个只读的编辑框,用于动态显示消费者与生产者问题的详细过程。
MFC界面设计如下图所示:
三、核心代码
本程序的特色在于将生产者-消费者问题的内部的进程调度的细节以及缓冲区的状态变化动态的呈现在MFC的界面上。
且程序中还实现了随机调度生产者进程和消费者进程。
以下主要介绍随机算法以及生产者进程动态描述的源代码。
消费者的代码,与生产者代码相似。
1.随机启动进程函数:
调用c++函数库中定义产生随机数的函数,生成整数随机数。
使用取模的方法判断,若为奇数则创建并启动生产者进程;反之则创建并启动消费者进程。
srand(time(NULL));
for(i=0, j=0;i<CWork::producer_tcount || j< CWork::consumer_tcount;){
if (i>=CWork::producer_tcount){
CThreads[j]= ::CreateThread(NULL,0,CWork::consumer,this,0,&consumerID[j ]);
::CloseHandle(CThreads[j]);
j++;
}
else if (j>=CWork::consumer_tcount){
PThreads[i]=::CreateThread(NULL,0,CWork::producer,this,0,&producerID[i] );
::CloseHandle(PThreads[i]);
i++;
}
else{
int n = rand()%2;
if (n == 0){
PThreads[i]=CreateThread(NULL,0,CWork::producer,this,0,&producerID[ i]);
::CloseHandle(PThreads[i]);
i++;
}
else{
CThreads[j]=CreateThread(NULL,0,CWork::consumer,this,0,&consumerID[ j]);
::CloseHandle(CThreads[j]);
j++;
}
}
}
2.生产函数:
实现生产者生产产品的过程,即将空闲缓冲区位置更改为满的缓冲区位置。
void CWork::produce(CMy20112880P_CDlg* pDlg){
CString str1,str2,str3;
str1="生产";
pDlg->SetDlgItemText(IDC_ONE,str1);
pDlg->SetDlgItemInt(IDC_TWO,product_num);
buffer[in]=product_num;
product_num++;
buffer_state[in]='@';
show_p(pDlg);
in=(in+1)%size;
::Sleep(1000);
}
3.生产者生产状态显示函数:
实现显示生产者生产产品后,动态显示相关信息。
void CWork::show_p(CMy20112880P_CDlg* pDlg)
{
CString result;
CString str2 (": " );
CString str1;
CString str5("\r\n");
CString str4 (" <------生产");
for(int i=0;i<size;++i)
{
str1.Format("%d", i);
CString str3(buffer_state[i]);
result=result+str1+str2+str3 ;
if(i==in)
result=result + str4;
result=result+str5;
}
pDlg->SetDlgItemText(IDC_OUT,result);
::Sleep(1000);
}
四、设计结果及数据评测
测试1:输入的生产者数量、消费者数量、缓冲区大小分别为1,1,1。
即单生产者消费者单缓冲区。
测试截图如下:
单生产者消费者多缓冲区。
测试截图如下:
测试3:输入的生产者数量、消费者数量、缓冲区大小分别为4,4,1。
即多生产者消费者单缓冲区。
测试截图如下:
多生产者消费者多缓冲区。
测试截图如下:
五、设计中的问题及思考
本次课程设计是我学习编写代码以来实现的最为底层的程序。
第一次接触WINAPI的一下几个函数:CreateMutex,CreateSemaphore,WaitForSingleObject,ReleaseMutex,ReleaseSemaphore,CreateThread。
与此同时,通过本次课程设计,从之前的抽象理解到现在的具体实现,我对生产者-消费者问题有了更加深入的了解。
本次课程设计中遇到的难点有如下两个:
第一个难点是WINAPI的函数调用,每个函数调用时都需要设置很多不同的实参,如CreateThread函数的使用,首先需要理解每个参数的意义,其次就是了解这个函数的返回值类型。
由于本程序的设计支持多生产者多消费者,所以获取输入的生产者与消费者的数目之后,需要为生产者与消费者分别分配两个数组,一个数组存放的是进程,另一个数组存放的是进程ID号,两个数组同步操作,完成进程的创建与调用。
第二个难点是多线程与MFC的连接问题,及怎样将缓冲区状态、进程状态等动态的显示出在MFC界面上。
我通过SetDlgItemText函数对MFC编辑框中的内容进行更新,而更新的过程是这样的,以生产者为例:生产者进程函数调用生产函数,生产函数在调用状态显示函数。
这样就可以实现每个进程在执行状态时,进程状态以及其对应的缓冲区的状态都可以同步显示。
解决以上难点之后,对程序进行测试,分别测试了单生产者消费者单缓冲区、单生产者消费者多缓冲区、多生产者消费者单缓冲区、多生产者消费者多缓冲区几种不同的情况,其测试均得到正确结果,符合理论和实际。