操作系统:生产者-消费者问题

生产者-消费者问题

一.问题描述

系统中有一组生产者进程和消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。

其中,缓冲区的容量为n。

操作系统:生产者-消费者问题

 上图是生产者-消费者问题的模型图


二.解题思路

根据题意存在互斥与同步关系

互斥

1.生产者与生产者之间存在互斥关系,因为缓冲区属于临界资源,同时有两个生产者占用时会出现重写现象。

2.消费者与消费者之间存在互斥关系,因为消费者占用缓冲区时,会直接取出数据,当多个消费者占用时,会出现访问错误。

3.生产者与消费者之间存在互斥关系。

同步

1.当缓冲区没有数据时,生产者先占用缓冲区,生产数据,消费者才能占用缓冲区,取出数据。

2.当缓冲区满的时候,消费者先占用缓冲区,取出数据,生产者才能占用缓冲区,生产数据。


 当缓冲区为5时,代码如下:

semaphore mutex=1,empty=5,full=0
//p0生产者
p0(    ){
    while(1){
        生产数据
        p(empty);    //实现消费者先占用缓冲区,取出数据,生产者才能占用缓冲区,生产数据。
        p(mutex);    //实现互斥
        把数据放进缓冲区
        v(mutex);
        v(full);    
    }
}
//p1消费者
p1(    ){
    while(1){
        p(full);    //实现生产者先占用缓冲区,生产数据,消费者才能占用缓冲区,取出数据。
        p(mutex);    //实现互斥
        从缓冲区取出一个产品
        v(mutex);
        v(empty);
        使用数据
    }
}

 

mutex=1,p(mutex),v(mutex)实现互斥

当生产者运行代码时,运行过p(mutex)时,mutex为0,如果进程调用到消费者或者其他生产者时,运行到p(mutex)时,由于mutex=0进程会进入阻塞队列,只有运行到之前生产者的v(mutex)时,才能访问其他消费者或者生产者。


前v后p实现同步操作

full=0,p0{  ...v(full);  },p1{  p(full);...  }由于full=0只有先由p0生产者运行完,full=1后,p1才能运行。

empty=5,代表缓冲区的容量为5,每经历一个p(empty),存入数据,缓冲区减一,为防止缓冲区满的时候,生产者继续存入数据。p0{  p(empty);...  },p1{  ...v(empty);  },当数据存入5个时,empty=0,p0生产者运行p(empty),将进入阻塞态,只有运行p1的v(empty)后,empty-1,生产者才能继续访问缓冲区存数据。


注:互斥的p操作一定要在实现同步的p操作之后

交换后

semaphore mutex=1,empty=5,full=0
//p0生产者
p0(    ){
    while(1){
        生产数据
        p(mutex);    //实现互斥
        p(empty);    //实现消费者先占用缓冲区,取出数据,生产者才能占用缓冲区,生产数据。
       
        把数据放进缓冲区
        v(mutex);
        v(full);    
    }
}
//p1消费者
p1(    ){
    while(1){
        p(mutex);    //实现互斥
        p(full);    //实现生产者先占用缓冲区,生产数据,消费者才能占用缓冲区,取出数据。
        
        从缓冲区取出一个产品
        v(mutex);
        v(empty);
        使用数据
    }
}

假如empty=0,mutex=1,运行p0,运行p(mutex);p(empty);后mutex=0,同时由于empty=0,p0进程进入阻塞态,调用p1进程,运行 p(mutex);由于mutex=0,所以p1也进入阻塞态造成了“死锁”。


上一篇:项目数据突然查询不到:非代码问题 : sql_mode=only_full_group_by


下一篇:进程的同步与互斥之生产者消费者问题:对信号量设置的理解及PV操作顺序分析