生产者和消费者问题中的唤醒丢失(操作系统)

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

#define N 100
int count = 0;
void producer(void)
{
 int item;
 while(TRUE)
 {
  item = produce_item();
  if(count == N)     //如果缓冲区满就休眠
  sleep();
  insert_item(item);
  count = count + 1;    //缓冲区数据项计数加1
  if(count == 1)
  wakeup(consumer);
 }
}
 
void consumer(void)
{
 int item;
 while(TRUE)
 {
  if(count == 0)    //如果缓冲区空就休眠
   sleep();
  item = remove_item();
  count = count - 1;   //缓冲区数据项计数减1
  if(count == N - 1)
   wakeup(producer);
  consume_item(item);
 }
}

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

在这里“逻辑上”是指
-----------当消费者进程检测到count等于0时,在还没有运行sleep()时消费者进程时间片到期,消费者进程变成runnable状态,生产者这时候被调度运行,当count变为1时,生产者试图唤醒消费者,此时对于消费者来说唤醒是无效的,因为消费者根本没有运行到sleep(),,wakeup信号丢失,所以说在逻辑上并未睡眠。当时间片被转到消费者时,这时候消费者进程被调度,执行完sleep()后,消费者进程才真正进入逻辑上得睡眠。尽管count已经非零了,但是再也不会有唤醒信号了,它将永远沉睡。归根到底是因为这里对count的访问不是原子性的。

你可能感兴趣的:(笔记,java,开发语言)