首页 > 代码库 > 生产者-消费者问题

生产者-消费者问题

    生产者-消费者问题有时也称作有界缓冲区问题。

    两个进程共享一个固定大小的缓冲区,生产者将信息放入缓冲区,消费者从缓冲区中取出信息。

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

 1 #define N 100                                      /*缓冲区中的槽数目*/ 2 int count = 0;                                     /*缓冲区中的数据项数目*/ 3  4 //producer 5 void producer(void)     6 { 7   int item; 8  9   while(TRUE){                                     /*无限循环*/10     item = produce_item();                         /*产生下一新数据项*/11     if(count == N) sleep();                        /*如果缓冲区满了,就进入休眠状态*/12     insert_item(item);                             /*将(新)数据项放入缓冲区中*/13     count = count + 1;                             /*将缓冲区的数据项计数器增1*/14     if(count == 1) wakeup(consumer);               /*缓冲区空吗?*/15     }         16 }17 18 //consumer19 void consumer(void)20 {21 while(TRUE){                                       /*无限循环*/22     if(count == 0) sleep();                        /*如果缓冲区空,则进入休眠状态*/23     item = remove_item();                          /*从缓冲区中取出一个数据项*/24     count = count - 1;                             /*将缓冲区的数据项计数器减1*/25     if(count == N-1) wakeup(producer);             /*缓冲区慢吗?*/26     consume_item(item);                            /*打印数据项*/27     }         28 }

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

    但是,消费者此时在逻辑上并未睡眠,所以wakeup信号丢失,当消费者下次运行的时候,他将测试先前读到的count值,发现他为0,于是睡眠。生产者迟早会填满整个缓冲区,然后睡眠!

    解决方法:唤醒等待位

生产者-消费者问题