标签:
之前介绍的几种解决进程间互斥的方案,不管是Peterson方案还是TSL指令的方式,都有一个特点:当一个进程被Block到临界区外面时,被Block的进程会一直处于忙等待的状态,这个不但浪费了CPU资源,还会有一个很坏的副作用。假设两个进程,H,L,H的优先级高,L进程的优先级非常低,CPU的调度规则是只要H处于Ready状态,则开始运行H,问题来了:
如果一个进程不容许进入临界区时,这个时候让这个进程block,则解决了无线等待问题,文章开头提出的问题也就解决了。怎么block进程。
示意图:
生产者消费者主要是当往Buffer插入数据的时候发现buffer已经满了,则让生产者sleep,而是不无限循环等待
当发现buffer没有数据的时候让消费者sleep,而不是无限循环等待。
当buffer有数据时候,但是发现之前消费者属于sleep状态,则让消费者wakeup。
当buffer没有数据时候,但是发现之前生产者处于sleep状态,则让生产者wakeup。
#definne N 100 //buffer 的容量
int count = 0; //buffer中item的数量
void producer(void)
{
int item;
while(true)//永远执行
{
item= produce_item();//生成下一个item
if(count == N)//如果buffer已经满了,则sleep
{
sleep();
}
insert_item(item);//将item放入buffer
count = count + 1;//数量+1
if(count == 1)//之前buffer是空的,所以consumer处于sleep状态,现在有item了,唤醒consumer
{
wakeup(consumer);
}
}
}
void consumer(void)
{
int item;
while(true)
{
if(count == 0)//如果buffer是空的,则sleep
{
sleep();
}
item = remove_item();//将item从buffer移除
count = count - 1;//数量-1
if(count == N - 1)//之前buffer已经满了,所以producer处于sleep状态,现在移除了一个item,唤醒producer
{
wakeup(producer);
}
consume_item(item);//消费item
}
}
上面的代码依然存在竞争条件问题(Race Conditions),考虑如下情况:
以上完成后,由于之前的消费者因为cpu的调度没有走到sleep状态,所以wakeup对消费者是不起作用的。所以wakeup的信号就丢失了。
继续:
最终结果:
上面问题的关键是wakeup指令发给了一个没有sleep的进程,wakeup不起作用,wakeup的型号最终丢失了。
一个快速的解决方案是给进程加一个Wakeup waiting Bit,当一个wakeup请求发给一个处于wakeup的进程时,将这个进程的Wakeup waiting Bit标志位设置为true。接下来当有sleep给这个进程时,判断一下如果Wakeup waiting Bit为true,则不sleep。
这个方法能暂时解决问题,但是很糟糕,如果有多个进程时,就需要很多标志位。接下来几篇文章会专门将信号量,互斥体等来解决生产者消费者的竞争条件问题。
Operating System-进程间互斥的问题-生产者&&消费者引入
标签:
原文地址:http://www.cnblogs.com/Brake/p/Operating_System_Producer_And_Consumer.html