Page 53 - 4868
P. 53
51 Ошибка! Стиль не определен.
Процеси Producer і Consumer повинні отримувати доступ до змінної
buf по черзі. Спочатку Producer поміщає перший елемент з масиву a в
змінну buf, потім Consumer витягує її із змінної buf, після чого Producer
поміщає в змінну buf наступний елемент з масиву a і так далі. Нехай спільні
змінні p та c виступають лічильниками числа поміщених і витягнутих
елементів. Їхні початкові значення дорівнюють 0. Тоді умови для
синхронізації процесів Producer і Consumer можуть бути записані в
наступному вигляді:
PC: c<= p<= c+1
Значення змінних c та p можуть відрізнятися не більше ніж на 1. Це
означає, що Producer помістив у буфер максимум на один елемент більше,
ніж Consumer витягнув. Код цих двох процесів приведений в лістингу 1.2.
Процеси Producer і Consumer використовують змінні p та c для
синхронізації доступу до буфера buf. Оператори await застосовуються для
призупинення процесів до тих пір, поки буфер не стане повним або
порожнім. Якщо умова p == c істинна, то буфер порожній (останній
поміщений в нього елемент був витягнутий), а якщо p > c – заповнений.
Лістинг 1.2 – Копіювання масиву від «виробника» до «споживача»
int buf, p = 0, c = 0;
process Producer {
int a[n];
while (p <n) {
< await (p == c);>
buf = a[p];
p = p+1;
}
}
process Consumer {
int b[n];
while (c <n) {
< await (p> c);>
b[c] = buf;
c = c+1;
}
}
Якщо синхронізація реалізується описаним способом, то говорять, що
процес знаходиться в стані активного очікування, або зациклений, оскільки
він зайнятий перевіркою умови в операторі await, але все, що він в даному
випадку робить – це повторення циклу до тих пір, доки умова не
виконається. Це звичайний тип синхронізації, що реалізується на найнижчих
рівнях програмних систем, наприклад, в операційних системах та мережевих
протоколах.