【操作系统总结】经典的进程同步问题-生产者消费者问题

时间:2021-06-12 20:22:19

生产者消费者问题

问题描述是:有一群生产者进程在生产产品,此产品提供给消费者去消费。为使生产者和消费者进程能并发执行,在它们之间设置一个具有n个缓冲池,生产者进程可将它所生产的产品放入一个缓冲池中,消费者进程可从一个缓冲区取得一个产品消费。

利用记录型信号量

semaphore mutex=1,empty=n,full=0;
item buffer[n];   //缓冲区
int in=out=0;   //输入、输出指针
void producer()  

{    

     while(1)
    {    
         …
         生产一个产品nextp;
        …
        wait(empty);  //首先对empty--判断他是否小于0,小于0就自我阻塞
        wait(mutex);  //拿到锁,否则就自我阻塞 

        buffer[in]= nextp; //往Buffer [in]放产品
        in = (in+1) % n;
        signal(mutex);  //释放锁
        signal(full);   //对full++判断是否<=0,如果是就唤醒进程
   }
}

void consumer()  
{    
     while(1)
    {   ……
        wait(full); //首先对full--判断他是否小于0,小于0就自我阻塞
        wait(mutex); //拿到锁,否则就自我阻塞
        nextc = buffer[out]; //从Buffer [out]取产品
        out = (out +1) mod n;
        signal(mutex); //释放锁
        signal(empty); //对empty++判断是否<=0,如果是就唤醒进程
                                   消费nextc产品;
      }
}

main()
{
    cobegin{
    producer();
    consumer();
}

利用AND型信号量

semaphore mutex=1,empty=n,full=0;
item buffer[n];   //缓冲区
int in=out=0;   //输入、输出指针
void producer()  

{    

     while(1)

    {    

    …
      生产一个产品nextp;
    …
    swait(empty, mutex);//当empty和mutex都大于0,否则自我阻塞
    buffer[in]= nextp; //往Buffer [in]放产品
    in = (in+1) mod n;
    ssignal(mutex, full);//把锁设回来,然后full+1
     }

}

void consumer()  

{    

     while(1)

    {        

        ……

        swait(full, mutex);当full和mutex都大于0,否则自我阻塞
        nextc = buffer[out];  //从Buffer [out]取产品
        out = (out +1) mod n;
        signal(mutex, empty);把锁设回来,然后empty+1
            消费nextc产品;
         }
}

利用管程

//建立一个管程结构
Monitor produceconsumer {
    item buffer[N];//缓冲区
    int in, out;
    condition notfull, notempty;
    int count;
    public:
    void put(item x) {
        if(cout >= N) cwait(notfull);//如果里面的量已经等于N,就让这个进程阻塞
        buffer[in]  = x;//否则就放东西
        in = (in + 1) % N;
        count++;
        csignal(notempty);//如果不为空就唤醒消费者进程
    }

    void get(item x) {
        if(count <= 0) cwait(notempty);//如果是空,就让这个进程阻塞
        x = buffer[out];
        out = (out + 1) % N;
        count--;
        csignal(notfull);//不满的话就唤醒生产者进程
    }

    {
        in = 0;
        out = 0;
        count = 0;
    }
}PC;

void producer() {
    item x;
    while(1) {
        在缓冲区放东西
        PC.put(x);
    }
}

voif consumer() {
    item x;
    while(1) {
        PC.get(x);
        从缓冲区取东西
    }
}

void main() {
    cobegin;
    proceducer();
    consumer();
    conend;
}