一 消费者——生产者问题
1 思路:两个进程共享一个公共的固定大小的缓冲区,其中一个是生产者将信息放入缓冲区,另外一个是消费者,从缓冲区取出信息。当缓冲区已满,此时生产者还想向其中放入一个新的数据项,解决办法是让生产者睡眠,待消费者从缓冲区取出一个或者多个数据时再唤醒它。同样,当消费者从缓冲区取出数据时发现缓冲区为空时,消费者就睡眠,直到生产者向其中放入一些数据时再将其唤醒。
解法一
#define N100//缓冲区中的槽目数
int count =0;//缓冲区中的数据项目
void producer(void)
{
int item;
while (TRUE)//无限循环
{
item =produce_item();//产生下一新数据项
if(count==N)sleep();//如果缓冲区满了,就进入休眠状态
inert_item(item);//将新数据项放入缓冲区中
count=count+1;//将缓冲区中的数据项计数器加一
if(count==1)wakeup(consumer);//判断缓冲区是否为空
}
}
void consumer(void)
{
int item;
while (TRUE) //无线循环
{
if (count==0)sleep();//如果缓冲区空,则进入休眠状态
item =remove_item();//从缓冲区中取出一个数据项
count =count-1;//将缓冲区中的数据项计数器减一
if(count ==N-1)wakeup (producer);//判断缓冲区是否已满
consume_item(item);//打印数据项
}
}
2 缺点: (导致生产者进程跟消费者进程同时永远休眠下去)对count 的访问没有限制有可能造成:缓冲区为空,消费者刚读取 count值为零,此时调度程序决定暂停消费者并唤醒生产者。生产者向缓冲区加入一个数据项,count加一,当count变成1时进程推断认为之前的count为0,发现count为零时候消费者进程进入睡眠,于是生产者进程占满了整个缓冲区,然后睡眠。
3 解决方法:加入一个唤醒等待位
解法二
利用信号量解决生产者消费者问题
1 解决思路 :使用三个信号量:
一个称为full,用于记录充满的缓冲槽数目,
一个称为empty,记录空的缓冲槽数目,
一个称为mutex,用来确保生产者和消费者不会同时访问缓冲区
full的初值为0 empty初值为缓冲槽中的槽数目,mutex初始为1 供两个或者多个进程使用的信号量,其初始值为1 保证同时只有一个进程进入临界区,称为二元信号量,每个进程在进入临界区都执行一个down操作,退出时执行一个up操作,实现互斥。
#define N 100//缓冲区中的槽数目
typedef int semaphore;//信号量是一种特殊的整型数据
semaphore mutex = 1;//控制对临界区的访问
semaphore empty = N;//计数缓冲区的空槽数目
semaphore full = 0;//计数缓冲区的满槽数目
void produce (void)
{
int item;
while(TRUE)//TURE为常量1
{
item = produce_item();//产生放在缓冲区中的一些数据
down(&empty);//将空槽数目减一
down(&mutex);//进入临界区
insert_item(item);//将新数据项放入缓冲区
up(&mutex);//离开临界区
up(&full);//将满槽数目加1
}
}
void consume(void)
{
int item;
while(TURE)//无限循环
{
down(&full);//满槽数目加一
down(&mutex);//进入临界区
item =remove_item();//从缓冲区取出数据项
up(&mutex);//离开临界区
up(&empty);//将空槽数目加一
consume_item(item);//处理数据项
}
}