生产者消费者问题设计

上传人:飞*** 文档编号:51731174 上传时间:2018-08-16 格式:PDF 页数:10 大小:268.95KB
返回 下载 相关 举报
生产者消费者问题设计_第1页
第1页 / 共10页
生产者消费者问题设计_第2页
第2页 / 共10页
生产者消费者问题设计_第3页
第3页 / 共10页
生产者消费者问题设计_第4页
第4页 / 共10页
生产者消费者问题设计_第5页
第5页 / 共10页
点击查看更多>>
资源描述

《生产者消费者问题设计》由会员分享,可在线阅读,更多相关《生产者消费者问题设计(10页珍藏版)》请在金锄头文库上搜索。

1、一、设计目的本课程设计是学习完“操作系统原理”课程后进行的一次全面的综合训练,通过课程设计, 更好地掌握操作系统的原理及实现方法,加深对操作系统基础理论和重要算法的理解,加强学生的动手能力。二、设计内容(1)概述设计目的 : 通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制。说明: 有界缓冲区内设有20 个存储单元 , 放入/ 取出的数据项设定为1-20 这20 个整型数。设计要求 :(1) 每个生产者和消费者对有界缓冲区进行操作后, 即时显示有界缓冲区的全部内容 , 当前指针位置和生产者/ 消费者县城的标识符。 (2) 生产者和消费者各有两个以上。 (3) 多个生产者或多

2、个消费者之间须有共享对缓冲区进行操作的函数代码。(2)设计原理通过一个有界缓冲区把生产者和消费者联系起来。假定生产者和消费者的优先级是相同的,只要缓冲区未满,生产者就可以生产产品并将产品送入缓冲区。类似地,只要缓冲区未空,消费者就可以从缓冲区中取走产品。应该禁止生产者向满的缓冲区送入产品,同时也应该禁止消费者从空的缓冲区中取出产品,这一机制有生产者线程和消费者线程之间的互斥关系来实现。与计算打印两进程同步关系相同,生产者和消费者两进程P和 C之间应满足下列两个同步条件: 只有在缓冲池中至少有一个缓冲区已存入消息后,消费者才能从中提取信息,否则消费者必须等待。 只有缓冲池中至少有一个缓冲区是空时

3、,生产者才能把消息放入缓冲区,否则生产者必须等待。为了满足第一个同步条件,设置一个同步信号量full,它代表的资源是缓冲区满,它的初始值为 0,它的值为 n 时整个缓冲池满。这个资源是消费者类进程C所有, C进程可以申请该资源,对它施加P操作,而 C进程的合作进程生产者进程P对它施加 V操作。同样为了满足第二个同步条件,设置另一个同步信号量empty,它代表的资源是缓1 冲空区,它的初始值为 n,表示缓冲池中所有缓冲区空。 信号量 full表示可用缓冲区数量,信号量 empty 表示缓冲区数量,设置整型变量:存入指针in 和取出指针 out。为解决生产者 / 消费者问题,应该设置两个资源信号量

4、,其中一个表示空缓冲区的数目,用 g_hFullSemaphore 表示,其初始值为有界缓冲区的大小SIZE_OF_BUFFER;另一个表示缓冲区中产品的数目,用 g_hEmptySemaphore 表示,其初始值为 0. 另外,由于有界缓冲区是一个临界资源,必须互斥使用,所以还需要在设置一个互斥信号量g_hMutex,初始值为 1. P原语的主要动作是: sem减 1; 若 sem减一后仍大于或等于零,则进程继续执行; 若 sem减一后小于零,则该进程被阻塞后入与该信号相对应的队列中,然后转进程调度。V原语的操作主要动作是: sem加 1; 若相加结果大于零,进程继续执行;若相加结果小于或等

5、于零, 则从该信号的等待队列中唤醒一等待进程然后再返回原进程继续执行或转进程调度。采用的同步方法:1)利用函数 CreateMutex(NULL,FALSE,NULL)创建互斥信号量 g_hMutex,表示缓冲区当前的状态,若为true 时,则表示缓冲区正被别的进程使用。三个参数表示的意义分别为:指向安全属性的指针,初始化互斥对象的所有者, 指向互斥对象名的指针。2) 利用函数 CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1, NULL)创建缓冲区满的信号量 g_hFullSemaphore,值为true时表示缓冲区已满。 四个参数

6、分别为:表示是否允许继承、设置信号机的初始计数、设置信号机的最大计数、指定信号机对象的名称(-1是因为计数从开始)。3)利用函数 CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL) 创建缓冲区空的信号量 g_hEmptySemaphore ,该值为 true 时表示缓冲区为空。5、数据定义及其详细解释2 const unsigned short SIZE_OF_BUFFER = 20; /缓冲区长度unsigned short ProductID = 0; /产品号unsigned short ConsumeID = 0; /将被消耗的产品号unsign

7、ed short in = 0; /产品进缓冲区时的缓冲区下标unsigned short out = 0; /产品出缓冲区时的缓冲区下标int g_bufferSIZE_OF_BUFFER; /缓冲区是个循环队列bool g_continue = true; /使程序跳出循环,控制程序结束HANDLE g_hMutex; /用于线程间的互斥HANDLE g_hFullSemaphore; /当缓冲区满时迫使生产者等待HANDLE g_hEmptySemaphore; /当缓冲区空时迫使消费者等待DWORD WINAPI Producer(LPVOID); /生产者线程DWORD WINAPI

8、 Consumer(LPVOID); /消费者线程(3)详细设计及编码流程图生产者:消费者:sem=sem-1 入口s=0 调用进程入等待队列转进程调度返回是否3 程序清单1. 存储结构定义利用信号量解决生产者消费者问题const unsigned short SIZE_OF_BUFFER = 10; /缓冲区长度unsigned short ProductID = 0; /产品号unsigned short ConsumeID = 0; /将被消耗的产品号unsigned short in = 0; /产品进缓冲区时的缓冲区下标unsigned short out = 0; /产品出缓冲区时

9、的缓冲区下标int g_bufferSIZE_OF_BUFFER; /缓冲区是个循环队列bool g_continue = true; /控制程序结束HANDLE g_hMutex; /用于线程间的互斥HANDLE g_hFullSemaphore; /当缓冲区满时迫使生产者等待HANDLE g_hEmptySemaphore; / 当缓冲区空时迫使消费者等待DWORD WINAPI Producer(LPVOID); /生产者线程DWORD WINAPI Consumer(LPVOID); /消费者线程2. 算法相关的函数(1)创建各个互斥信号以及生产者线程和消费者线程的函数在如下主函数里面

10、所示:int main() /创建各个互斥信号g_hMutex = CreateMutex(NULL,FALSE,NULL); 入 口sem=sem-1 S=0 唤醒等待队列中的一个进程返回或转进程调度返回否是4 g_hFullSemaphore CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL); g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL); /调整下面的数值,可以发现,当生产者个数多于消费者个数时,/生产速度快,生产者经常等待消费者;

11、反之,消费者经常等待。const unsigned short PRODUCERS_COUNT = 3; /生产者的个数const unsigned short CONSUMERS_COUNT = 1; /消费者的个数/总的线程数const unsigned short THREADS_COUNT PRODUCERS_COUNT+CONSUMERS_COUNT; HANDLE hThreadsPRODUCERS_COUNT; /各线程的 handle DWORD producerIDCONSUMERS_COUNT; / 生产者线程的标识符DWORD consumerIDTHREADS_COUN

12、T; /消费者线程的标识符/创建生产者线程for (int i=0;i hThreadsi=CreateThread(NULL,0,Producer,NULL,0, if (hThreadsi=NULL) return -1; /创建消费者线程for ( i=0;i hThreadsPRODUCERS_COUNT+i=CreateThread(NULL,0,Consumer,NULL,0 if (hThreadsi=NULL) return -1; while(g_continue) if(getchar() /按回车后终止程序运行g_continue = false; return 0; (

13、2) 生产者生产一个产品的函数:/ 生产一个产品。简单模拟了一下,仅输出新产品的ID 号5 void Produce() std:cerr “Producing “ +ProductID “ * “; std:cerr “Succeed“ std:endl; (3)把新生产的产品放入缓冲区的函数:/ 把新生产的产品放入缓冲区void Append() std:cerr “Appending a product * “; g_bufferin = ProductID; in = (in+1)%SIZE_OF_BUFFER; std:cerr “Succeed“ std:endl; (4)输出缓冲

14、区当前的状态的函数:/输出缓冲区当前的状态for (int i=0;i std:cout i “: “ g_bufferi; if (i=in) std:cout “ - 生产“; if (i=out) std:cout “ - 消费“; std:cout std:endl; 从缓冲区中取出一个产品的函数:/ 从缓冲区中取出一个产品void Take() std:cerr “Taking a product * “; ConsumeID = g_bufferout; out = (out+1)%SIZE_OF_BUFFER; 利用信号量解决生产者消费者问题std:cerr “Succeed“ std:endl; 6 (5)输出缓冲区当前的状态的函数:/输出缓冲区当前的状态for (int i=0;i std:cout i “: “ g_bufferi; if (i=in) std:cout “ - 生产“; if (i=out) std:cout “ - 消费“; std:cout std:endl; (6)消耗一个产品的函数:/ 消耗一个产品void Consume() std:cerr “Consuming “ ConsumeID “ * “; std:cerr “Succeed“

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号