当前位置:文档之家› 生产者和消费者问题

生产者和消费者问题

课程设计题目生产者和消费者问题学院计算机科学与技术专业班级姓名指导教师吴利军2013 年 1 月16 日课程设计任务书学生姓名:指导教师:吴利军工作单位:计算机科学与技术学院题目: 进程同步模拟设计——生产者和消费者问题初始条件:1.预备内容:阅读操作系统的进程管理章节内容,对进程的同步和互斥,以及信号量机制度有深入的理解。

2.实践准备:掌握一种计算机高级语言的使用。

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.模拟用信号量机制实现生产者和消费者问题。

2.设计报告内容应说明:⑴需求分析;⑵功能设计(数据结构及模块说明);⑶开发平台及源程序的主要部分;⑷测试用例,运行结果与运行情况分析;⑸自我评价与总结:i)你认为你完成的设计哪些地方做得比较好或比较出色;ii)什么地方做得不太好,以后如何改正;iii)从本设计得到的收获(在编写,调试,执行过程中的经验和教训);iv)完成本题是否有其他方法(如果有,简要说明该方法);时间安排:设计安排一周:周1、周2:完成程序分析及设计。

周2、周3:完成程序调试及测试。

周4、周5:验收、撰写课程设计报告。

(注意事项:严禁抄袭,一旦发现,一律按0分记)指导教师签名:年月日系主任(或责任教师)签名:年月日生产者-消费者问题(the producer-consumer problem) 1.需求分析1.1问题描述:一组生产者向一组消费者提供消息,它们共享一个有界缓冲区n,生产者向其中投放消息,消费者从中取得消息。

1.2规则:⏹对于生产者进程:产生一个数据,当要送入缓冲区时,要检查缓冲区是否已满,若未满,则可将数据送入缓冲区,并通知消费者进程;否则,等待;⏹对于消费者进程:当它去取数据时,要看缓冲区中是否有数据可取,若有则取走一个数据,并通知生产者进程,否则,等待。

⏹缓冲区是个临界资源,因此,诸进程对缓冲区的操作程序是一个共享临界区,所以,还有个互斥的问题。

1.3信号灯设置:两个同步信号灯--empty :表示空缓冲区的数目,初值为有界缓冲区的大小n;full :表示满缓冲区(即信息)的数目,其初值为0;一个互斥信号灯--mutex:互斥信号灯,初值为1。

1.4同步描述:1.5程序描述:main( ){int full=0;/* 满缓冲区的数目 */int empty=n;/* 空缓冲区的数目 */int mutex=1;/* 对有界缓冲区进行操作的互斥信号灯*/cobeginp1 ( );p2( );coend}p1(){while(生产未完成){···生产一个产品;p(empty);p(mutex);送一个产品到有界缓冲区;v(mutex);v(full);}}p2( ){while(还要继续消费){p(full);p(mutex);从有界缓冲区中取产品;v(mutex);v(empty);···消费一个产品;}}1.6C++语言程序模拟用信号量机制实现生产者和消费者问题:本次课程设计主要通过C++模拟信号量制中各个进程,及各进程之间的互斥、同步关系,来实现生产者和消费者问题。

2.功能设计2.1设计目的:通过实验模拟生产者和消费者之间的关系,了解并掌握他们之间的关系及其原理。

由此增加对进程同步的问题的了解。

具体如下:1)掌握基本的同步互斥算法,理解生产者和消费者模型;2)了解windows中多线程(多进程)的并发执行机制,线程(进程)间的同步和互斥; 3)学习使用windows中基本的同步对象,掌握相应的API。

2.2设计功能:利用模拟用信号量机制实现生产者和消费者问题:通过用户控制取进程和放进程,反应生产者和消费者问题中所涉及的进程的同步与互斥。

2.3数据结构:2.4模块说明: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); //消费者线程3.开发平台及源程序的主要部分:3.1开发平台:基于VS2010开发平台的C++编程3.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]; //各线程的handleDWORD 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 (int j=0; j<CONSUMERS_COUNT; ++j){hThreads[PRODUCERS_COUNT+j]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[j ]);if (hThreads[j]==NULL) return -1;}while(g_continue){if(getchar()){ //按回车后终止程序运行g_continue = false;}}return 0;}//生产一个产品。

简单模拟了一下,仅输出新产品的ID号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;}4.测试用例,运行结果与运行情况分析:4.1测试用例:在本次课程设计的测试中,缓冲区长度是取值为10,生产者个数取值为3,消费者个数取值为1.4.2运行结果与分析:在测试中调整生产者和消费者的数值,可以发现,当生产者个数多于消费者个数时,生产速度快,生产者经常等待消费者;反之,消费者经常等待。

相关主题