14. Конкуренция: взаимно изключване и синхронизация
Монитори. Предаване на съобщения. Задачата на бръснаря

5.5 Монитори.
** Монитор със сигнал.
    Мониторите са програмни модули, състоящи се от една или повече процедури, инициализация и локални данни. Главни характеристики:
   1. Локалните данни са достъпни само от процедурите на монитора.
   2. Един процес "влиза в монитора" като извика някоя от процедурите му.
   3. Само един процес може да се изпълнява в монитора, всеки друг процес чака да се "освободи" монитора.
    Променливи на условия (condition variables). Функции с тези променливи:
- cwait(c):  Прекратяване изпълнението на процеса с условие c.  Мониторът е достъпен за друг процес;
- csignal(c): Въобновяване на изпълнението на процеса, прекратен с cwait със същото условие. Ако има няколко такива процеса се избира един от тях, ако няма - нищо не се прави.
    Разлика със семафорите - сигналът се "загубва", ако няма чакащи процеси за този сигнал.
--- FIGURE 5.22 ---
/* program producerconsumer */
monitor boundedbuffer;
char buffer[N];         /* space for N items */
int nextin, nextout;    /* buffer pointers */
int count;              /* number of items in buffer */
int notfull, notempty;  /* for synchronization */

void append (char x)
{
 if (count == N)
 cwait(notfull); /* buffer is оull;*/
                 /* avoid overflow */
 buffer[nextin] = x;
 nextin = (nextin + 1) % N;
 count++; /* one more item in buffer */
 csignal(notempty); 
/* resume any  waiting consumer */
}
void take (char x)
{
 if (count == 0)
 cwait(notempty); /* buffer is empty;*/
                  /* avoid underflow */
 x = buffer[nextout];
 nextout = (nextout + 1) % N;
 count--; /* one fewer item in buffer */
 csignal(notfull); 
/* resume any  waiting producer */
}
{
 /* monitor body */
 nextin = 0; nextout = 0; count = 0; /* buffer initially empty */
}
void producer()
{ char x;
  while (true)
  {
   produce(x);
   append(x);
  }
}
void consumer()
{ char x;
  while (true)
  {
   take(x);
   consume(x);
  }
}
void main()
{ parbegin(producer, consumer);
}
** Монитори със съобщения и разпространение.


5.6 Предаване на съобщения.
    Синхронизация и комуникация са двата проблема на взаимодействащи си процеси - взаимно изключване и обмен на информация. Двете задачи се решават с обмен на съобщения. Дефинират се два примитива (процедури):
send(destination, message)
receive(source, message)
Съществуват различини възможности за реализация на тези 2 процедури:
 
Synchronization Addressing  Format
Send Direct Content
    blocking     send Length 
    nonblocking     receive     fixed
Receive         explicit     variable
    blocking         implicit
    nonblocking Indirect
    test for arrival     static Queuing Discipline
    dynamic FIFO
    ownership Priority
** Синхронизация.
    Send -  процесът се блокира, докато събощението бъде получено (blocking send) или процесът не се блокира (nonblocking send).
    Receive - ако съобщението е изпратено, то се получава и процесът продължава. Ако не е изпратено: процесът се блокира до изпращане и получавене на съобщението (blocking receive) или процесът продължава, изоставяйки опитите за получаването му (nonblocking receive).
    Възможни са 3 комбинации :
-- Blocking send, blocking receive;
-- Nonblocking send, blocking receive - най-често срещано, при грешка, могат де се генерират много съобщения;
-- Nonblocking send, nonblocking receive.
** Адресиране.
--- FIGURE 5.24 ---
** Формат на съобщенията.
--- FIGURE 5.25 ---
** Дисциплина на опашките.

5.6 Задачата на бръснаря.
--- FIGURE 5.16 ---