睡眠与唤醒,生产者消费者问题

Peterson解法和TSL或XCHG解法都是正确的,但它们都有忙等待的缺点。这些解法在本质上是这样的:当一个进程想进入临界区时,先检查是否允许进入,若不允许,则该进程将原地等待,直到允许为止。

这种方法不仅浪费了CPU时间,而且还可能引起预想不到的结果。考虑一台计算机有两个进程,H优先级较高,L优先级较低。调度规则规定,只要H处于就绪态它就可以运行。在某一时刻,L处于临界区中,此时H变到就绪态,准备运行(例如,一条I/O操作结束)。现在H开始忙等待,但由于当H就绪时L不会被调度,也就无法离开临界区,所以H将永远忙等待下去。这种情况有时被称作优先级反转问题(priority inversion problem)。

现在来考察几条进程间通信原语,它们在无法进入临界区时将阻塞,而不是忙等待。最简单的是sleep和wakeup。sleep是一个将引起调用进程阻塞的系统调用,即被挂起,直到另外一个进程将其唤醒。wakeup调用有一个参数,即要被唤醒的进程。另一种方法是让sleep和wakeup各有一个参数,即有一个用于匹配sleep和wakeup的内存地址。

生产者-消费者问题

也称有界缓冲区(bounded-buffer)问题。两个进程共享一个公共的固定大小的缓冲区。生产者,将信息放入缓冲区;消费者,从缓冲区中取出信息。(也可以把这个问题一般化为m个生产者和n个消费者问题,但是我们只讨论一个生产者和一个消费者的情况,这样可以简化解决方案。)

问题在于当缓冲区已满,而此时生产者还想向其中放入一个新的数据项时让生产者睡眠,待消费者从缓冲区中取出一个或多个数据项时再唤醒它。同样地,当消费者试图从缓冲区中取数据而发现缓冲区为空时,消费者就睡眠,直到生产者向其中放入一些数据时再将其唤醒。

这个方法包含与前边假脱机目录问题一样的竞争条件。为了跟踪缓冲区中的数据项数,我们需要一个变量count。如果缓冲区最多存放N个数据项,则生产者代码将首先检查count是否达到N,若是,则生产者睡眠;否则生产者向缓冲区中放入一个数据项并递增count的值。

消费者的代码与此类似:首先测试count是否为0,若是,则睡眠;否则从中取走一个数据项并递减count的值。每个进程同时也检测另一个进程是否应被唤醒,若是则唤醒之。生产者和消费者的代码如图2-27所示。

 

图2-27   含有严重竞争条件的生产者-消费者问题

为了在C语言中表示sleep和wakeup这样的系统调用,以库函数调用的形式来表示。尽管它们不是标准C库的一部分,但在实际上任何系统中都具有这些库函数。未列出的过程insert_item和remove_item用来记录将数据项放入缓冲区和从缓冲区取出数据等事项。

这里有可能会出现竞争条件,其原因是对count的访问未加限制。有可能出现以下情况:缓冲区为空,消费者刚刚读取count的值发现它为0。此时调度程序决定暂停消费者启动运行生产者。生产者向缓冲区中加入一个数据项,count加1。现在count的值变成了1。它推断认为由于count刚才为0,所以消费者此时一定在睡眠,于是生产者调用wakeup来唤醒消费者。

但是,消费者此时在逻辑上并未睡眠,所以wakeup信号丢失。当消费者下次运行时,它将测试先前读到的count值,发现它为0,于是睡眠。生产者迟早会填满整个缓冲区,然后睡眠。这样一来,两个进程都将永远睡眠下去

问题的实质在于发给一个(尚)未睡眠进程的wakeup信号丢失了。如果它没有丢失,则一切都很正常。一种快速的弥补方法是修改规则,加上一个唤醒等待位。当一个wakeup信号发送给一个清醒的进程信号时,将该位置1。随后,当该进程要睡眠时,如果唤醒等待位为1,则将该位清除,而该进程仍然保持清醒。唤醒等待位实际上就是wakeup信号的一个小仓库。

尽管在这个简单例子中用唤醒等待位的方法解决了问题,但是我们很容易就可以构造出一些例子,其中有三个或更多的进程,这时一个唤醒等待位就不够使用了。于是我们可以再打一个补丁,加入第二个唤醒等待位,甚至是8个、32个等,但原则上讲,这并没有从根本上解决问题。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值