二、操作系统进程管理(11)——经典同步问题(1)生产者消费者问题

1.生产者消费者问题:


    (1)问题分析:系统中有一组生产者进程和消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区取出一个产品并使用。(产品:可以理解为某种数据)
        生产者、消费者共享一个初始为空、大小为n的缓冲区。
        只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。
            ——同步关系。缓冲区满时,生产者要等待消费者取走产品。
        只有缓冲区不空时,消费者才能从缓冲区取走产品,否则必须等待。
            ——同步关系。缓冲区为空时,消费者要等待生产者放入产品。
        缓冲区是临界资源,各进程必须互斥地访问。
            ——互斥。


    (2)可以用信号量机制(P、V操作)实现生产者、消费者进程的这些功能。


    (3)信号量机制可实现互斥、同步、对一类系统资源的申请和释放。
        互斥:设置初值为1的互斥信号量。
        同步:设置初值为0的同步信号量(实现"一前一后")。
        对一类系统资源的申请和释放:设置一个信号量,初始值即为资源的数量。(本质上也属于"同步问题",若无空闲资源,则申请资源的进程需要等待别的进程释放资源后才能继续往下执行)


    (4)P、V操作题目分析步骤:
        ①关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
        ②整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
            生产者每次要消耗(P)一个空闲缓冲区,并生产(V)一个产品。
            消费者每次要消耗(P)一个产品,并释放一个空闲缓冲区(V)。
            往缓冲区放入/取走产品需要互斥。
        ③设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初始值要看对应资源的初始值是多少)

    (5)如何实现:

mutex:互斥锁。

     (6)能否改变相邻P、V操作的顺序:

若此时缓冲区内已经放满产品,则empty=0,full=n。

按照①->②->③ 的顺序执行,生产者进程执行①使得mutex变为0,再执行②,由于已没有空闲缓冲区,因此生产者被阻塞。此时切换回消费者进程,执行③,由于mutex为0,即生产者还没释放对临界资源的"锁",因此消费者也被阻塞。

这就造成了生产者等待消费者释放空闲缓冲区,而消费者由等待生产者释放临界区的情况,生产者和消费者循环等待被对方唤醒,出现"死锁"。

若缓冲区没有产品,即full=0,empty=n。

按照③->④->①的顺序执行也会发生死锁。

因此,实现互斥的P操作一定要放在实现同步的P操作之后。

 V操作不会导致进程阻塞,因此两个V操作顺序可以交换。

      (7)小结:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验题目: 生产者与消费者(综合性实验) 实验环境: C语言编译器 实验内容: ① 由用户指定要产生的进程及其类别,存入进入就绪队列。    ② 调度程序从就绪队列中提取一个就绪进程运行。如果申请的资源被阻塞则进入相应的等待队列,调度程序调度就绪队列中的下一个进程进程运行结束时,会检查对应的等待队列,激活队列中的进程进入就绪队列。运行结束的进程进入over链表。重复这一过程直至就绪队列为空。    ③ 程序询问是否要继续?如果要转直①开始执行,否则退出程序。 实验目的: 通过实验模拟生产者与消费者之间的关系,了解并掌握他们之间的关系及其原理。由此增加对进程同步问题的了解。 实验要求: 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程类型标号、进程系统号、进程状态、进程产品(字符)、进程链指针等等。 系统开辟了一个缓冲区,大小由buffersize指定。 程序中有三个链队列,一个链表。一个就绪队列(ready),两个等待队列:生产者等待队列(producer);消费者队列(consumer)。一个链表(over),用于收集已经运行结束的进程 本程序通过函数模拟信号量的操作。 参考书目: 1)徐甲同等编,计算机操作系统教程,西安电子科技大学出版社 2)Andrew S. Tanenbaum著,陈向群,马红兵译. 现代操作系统(第2版). 机械工业出版社 3)Abranham Silberschatz, Peter Baer Galvin, Greg Gagne著. 郑扣根译. 操作系统概念(第2版). 高等教育出版社 4)张尧学编著. 计算机操作系统教程(第2版)习题解答与实验指导. 清华大学出版社 实验报告要求: (1) 每位同学交一份电子版本的实验报告,上传到202.204.125.21服务器中。 (2) 文件名格式为班级、学号加上个人姓名,例如: 电子04-1-040824101**.doc   表示电子04-1班学号为040824101号的**同学的实验报告。 (3) 实验报告内容的开始处要列出实验的目的,实验环境、实验内容等的说明,报告中要附上程序代码,并对实验过程进行说明。 基本数据结构: PCB* readyhead=NULL, * readytail=NULL; // 就绪队列 PCB* consumerhead=NULL, * consumertail=NULL; // 消费者队列 PCB* producerhead=NULL, * producertail=NULL; // 生产者队列 over=(PCB*)malloc(sizeof(PCB)); // over链表 int productnum=0; //产品数量 int full=0, empty=buffersize; // semaphore char buffer[buffersize]; // 缓冲区 int bufferpoint=0; // 缓冲区指针 struct pcb { /* 定义进程控制块PCB */ int flag; // flag=1 denote producer; flag=2 denote consumer; int numlabel; char product; char state; struct pcb * processlink; …… }; processproc( )--- 给PCB分配内存。产生相应的的进程:输入1为生产者进程;输入2为消费者进程,并把这些进程放入就绪队列中。 waitempty( )--- 如果缓冲区满,该进程进入生产者等待队列;linkqueue(exe,&producertail); // 把就绪队列里的进程放入生产者队列的尾部 void signalempty() bool waitfull() void signalfull() void producerrun() void comsuerrun() void main() { processproc(); element=hasElement(readyhead); while(element){ exe=getq(readyhead,&readytail); printf("进程%d申请运行,它是一个",exe->numlabel); exe->flag==1? printf("生产者\n"):printf("消费者\n"); if(exe->flag==1) producerrun();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值