13. Конкуренция: взаимно изключване и синхронизация
Семафори. Задача за производител/потребител.

5.5 Задача за производител/потребител.
    Един или няколко производители генерират данни (записи, символи) и ги поставят в един буфер. Един потребител взема по една данна от буфера. Само един агент (производител или потребител) има достъп да буфера в даден момент.
--- FIGURE 5.11 ---

* Първи опит за решение със семафори:
/* program producer_consumer */
int n;
binary_semaphore s = 1;
binary_semaphore delay = 0;

     void producer()
     {
      while (true)
      {
/*p1*/ produce();
/*p2*/ waitB(s);
/*p3*/ append(); /*КС*/ 
/*p4*/ n++;
/*p5*/ if (n==1) signalB(delay);
/*p6*/ signalB(s);
      }
     }
     void consumer()
     {
      waitB(delay);
      while (true)
      {
/*c1*/ waitB(s);
/*c2*/ take();    /*КС*/
/*c3*/ n--;
/*c4*/ signalB(s);
/*c5*/ consume();
/*c6*/ if (n==0) waitB(delay);
      }
     }
void main()
{ n = 0;
  parbegin(producer, consumer);
}
    Семафорът s служи за взаимно изключване, семафорът delay - за чакане на потребителя, когато буферът е празен.
Проблем:
 
     
n
delay
1
Init
 
0
0
2
Producer
КС
0->1
0->1
p1->p2->p3->p4->p5->p6
3
Consumer
waitB(delay)
1
1->0
4
Consumer
КС
1->0
0
c1->c2->c3->c4->c5->
5
Producer
КС
0->1
0->1
p1->p2->p3->p4->
6
Consumer
if (n==0) waitB(delay)
1
1
->c6
7
Consumer
КС
1->0
1
c1->c2->c3->c4->c5->
8
Consumer
if (n==0) waitB(delay)
0
1->0
->c6
9
Consumer
КС
-1
0
c1->c2-> !!!

* Втори опит - решение:
int n;
binary_semaphore s = 1;
binary_semaphore delay = 0;

void producer()
{
 while (true)
 {
  produce();
  waitB(s);
  append();n++;
  if (n==1) signalB(delay);
  signalB(s);
 }
}
void consumer()
{ int m;  /* a local variable */
  waitB(delay);
  while (true)
  {
   waitB(s);
   take(); n--;  m = n;
   signalB(s);
   consume();
   if (m==0) waitB(delay);
  }
}
void main()
{ n = 0;
  parbegin (producer, consumer);
}
    Варианти на задачата - безкраен буфер и краен кръгов буфер.
--- FIGURE 5.15 ---