线程同步之生产者-消费者问题

时间:2021-09-29 20:21:15

生产者-消费者问题(The Producer-Consumer Problem)是并发处理中最常见的一类同步抽象描述。先考虑但缓冲区的情况:有一个生产者进程P和一个消费者进程C公用一个缓冲区,P生产产品放入缓冲区,C从缓冲区取产品来消费。

同步问题:P进程不能往“满”的缓冲区中放入产品,C进程不能从“空”的缓冲区中取产品。

互斥问题:缓冲区不能同时被P和C使用。

解决方法:设置两个信号量full,empty,full表示缓冲区是否有产品,初值为0,empty表示缓冲区是否为空,初值为1.

1、解决单缓冲区生产者-消费者问题的描述如下:

struct semaphore
{
int value;
pointer_PCB quene;
}
semaphore S;

semaphore empty = 1;

semaphore full = 0;

main()

{

cobegin

    producer();

   consumer();

coend();

}

生产者-消费者进程描述如下:

void producer()                                                            void consumer()

{                                                                                    {

   while(true)                                                                     while(true)

     {                                                                                           {

       生产一个产品;                                                                  P(fulll);

       P(empty);                                                                        从缓冲区去产品;

      送产品到缓冲区;                                                                V(empty);

      V(full);                                                                               消费产品;

     }                                                                                             }

}                                                                                           }

2、考虑多个缓冲区的情况:设有若干个生产者进程P1,P2,···,Pn,若干个消费者进程C1,C2,···,Cm,它们通过一个缓冲池(由k个缓冲区组成)联系起来,如图所示

                                                                        线程同步之生产者-消费者问题

设每个缓冲区存放一个“产品”,生产者进程不断的生产产品,并把它们放入到缓冲池中,消费者进程不断的从缓冲池中取出产品并消费。

同步问题:当缓冲池已经放满了产品时,生产者进程必须等待;当缓冲池已空时,消费者进程必须等待

互斥问题:互斥存在于所有进程之间,所有进程应互斥使用缓冲池这一临界资源

为了了解生产者-消费者问题,需设置若干信号量:full,empty,mutex.其中mutex是互斥信号量,用于对缓冲池这一临界资源的互斥访问;full,empty是同步信号量,分别表示缓冲池满和空的数量。

void main()

{

 int full(0),empty(0),mutex(1);

int in = out = 0;

buffer[n];

cobegin

   producer();

   consumer();

coend

}

void producer()

{

   while(true)

     {

        ···

        Producer an item in nextp;//生产一件产品

       ···

        P(empty);

        P(mutex);

        buffer[in] = nextp;//向缓冲区存放一件产品

        in = (in +1)%n;

        V(mutex);

        V(full);

      }

}

void consumer()

{

   while(true)

     {

         P(full);

         P(mutex); 

         nextc = buffer[out];//从缓冲区取走一件产品

         out = (out+1)%n;

         V(mutex);

         V(empty);

        consumer the item nextc;//消费一件产品

     }

}