计算机操作系统学习之生产者消费者问题

一.问题描述

  • 系统中有一组生产者进程和一组消费者进程
  • 生产者和消费者共享一个初始为空、大小为n的缓存区
  • 生产者进程每次生产一个进程放入缓存区,消费者进程每次从缓存区取出一个进程并使用
  • 只有缓存区没满时,生产者才可以把产品放入缓存区,否则必须等待
  • 只有缓冲区不空时,消费者才可以从缓冲区取出产品,否则必须等待
  • 缓冲区是临界资源,各进程必须互斥的访问

二.使用信号量机制实现

1.关系分析

找出题目中各个进程的同步和互斥关系

  • 互斥:缓冲区是临界资源,各进程必须互斥访问
  • 同步1:缓存区满时,生产者要等待消费者取走产品(即缓冲区满时,生产产品在取走产品之后)
  • 同步2:缓存区空时,消费者要等待生产者生产产品(即缓存区空时,取走产品在生产产品之后)

2.整理思路

根据各进程的操作流程确定P、V操作的大致顺序

  • 生产者每次消耗(P)一个空闲缓冲区,并生产(V)一个产品
  • 消费者每次消耗(P)一个产品,并生产(V)一个空闲缓冲区
  • 往缓存区放入/取走产品需要互斥,即要设置一个初值为1的互斥信号量,在临界区之前和之后分别执行它的P、V操作

3.设置信号量

设置需要的信号量,并根据题目确定信号量初值
1.互斥信号量初值一般为1
2.同步信号量初值要看对应资源的初始值

  • 题目中一开始空闲缓冲区的数量为n,产品(非空闲缓冲区)的数量为0那么就可以设置如下信号量:
    在这里插入图片描述

4.具体的实现

(1)生产者

在这里插入图片描述

  • P(empty):消耗一个空闲缓冲区
  • V(full):生产一个产品
  • P(mutex)和V(mutex):实现进程互斥,分别在临界区之前和之后执行

(2)消费者

在这里插入图片描述

  • P(full):消耗一个产品
  • V(empty):生产一个空闲缓冲区
  • P(mutex)和V(mutex):实现进程互斥,分别在临界区之前和之后执行
  • 可以发现在实现进程互斥时,那一对P、V操作是在同一进程内执行的;在实现进程同步时,那一对P、V操作是分别在两个进程中执行的

5.P(empty)和P(mutex)顺序问题

可以看到在上面的实现过程中,P(empty)和P(full)在前,P(mutex)在后,那么能否交换它们两个的顺序呢?

  • 假设此时缓存区已满,则full=n,empty=0
  • 如果此时先执行P(mutex),使得mutex变成0,就是对临界资源上了锁
  • 然后再执行P(empty)去消耗一个空闲缓存区,会发现此时empty=0,已经没有空闲缓冲区可以使用,因此生产者会被阻塞
  • 由于生产者进程此时被阻塞,那么就会切换回消费者进程,先执行P(mutex),此时它会发现mutex=0,也就是说临界区此时仍然处于上锁状态没有被释放,那么此时消费者进程也被阻塞
  • 这就造成了生产者等待消费者释放空闲缓冲区,而消费者等待生产者释放临界区,出现死锁,因此不能交换顺序
  • 因此实现互斥的P操作一定要在实现同步的P操作之后
  • V操作不会导致进程阻塞,因此V(full)和V(mutex)顺序可以交换
  • 生产一个产品和使用产品的操作最好是放到临界区之外
    虽然从逻辑上看这两个操作放到临界区之内是没有问题的,但是将其放入临界区之后,临界区代码量就会变大,那么生产者/消费者进程在访问临界区时就需要耗费更长的时间,如果此时有别的进程想要访问临界区,那么它就会被阻塞,这就降低了进程的并发度。
  • 10
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值