Page 93 - 4868
P. 93
91 Ошибка! Стиль не определен.
кожен процес-споживач Consumer – операції P(full) та V(empty).
4.Задача кільцевих буферів (облік ресурсів). В останньому прикладі
продемонстровано синхронний доступ до одного буфера обміну. Якщо дані
створюються та видаляються приблизно з однаковою частотою, то процесу
не доводиться довго чекати доступу до буфера. Проте зазвичай споживач і
виробник працюють нерівномірно. Наприклад, виробник може швидко
створити відразу кілька елементів, а потім певний проміжок часу виконувати
обчислення перед створенням наступної серії елементів. У таких випадках
збільшення ємності буфера може істотно підвищити продуктивність
програми, зменшуючи число блокувань процесів. Даний випадок є
прикладом класичного компромісу між часом обчислень і об’ємом пам’яті.
Розглянемо рішення задачі про кільцевий буфер, який використовується
в якості багатоелементного комунікаційного буфера. На початковому етапі
припустимо, що існує тільки один виробник та споживач. Виробник
розміщує повідомлення в спільному буфері, а споживач витягує їх звідти.
Буфер містить чергу вже поміщених, але ще не витягнутих повідомлень. Така
черга може бути представлена зв’язаним списком або масивом. Отже, нехай
буфер буде масивом buf[n], де n > 1. Нехай змінна front – індекс
першого повідомлення черги, a rear – індекс першої порожньої комірки
після повідомлення в кінці черги. Спочатку змінні front та rear мають
однакові значення, наприклад, 0.
При такому представленні буфера виробник поміщає в нього
повідомлення із значенням data, виконуючи для цього наступні дії:
buf[rear] = data;
rear = (rear+1) % n;
Аналогічно споживач витягує повідомлення в свою локальну змінну
result, виконуючи дії:
result = buf[front];
front = (front+1) % n;
Оператор взяття залишку (%) використовується для того, щоб значення
змінних front та rear завжди були в межах від 0 до n-1. Черга
буферизованих повідомлень зберігається в комірках включно від
buf[front] до buf[rear] (не включно). Змінна buf інтерпретується як
кільцевий масив, в якому за значенням buf[n-1] слідує значення buf[0].
Ось приклад конфігурації масиву buf, де затемнені комірки заповнені, а білі
– вільні (рис. 1.16).
Рисунок 1.16 – Конфігурація масиву buf
Якщо використовується тільки один буфер (як у задачі «виробник-