Рекурсивні м’ютекси й умовні змінні



Рекурсивні м’ютекси не можуть бути використані у поєднанні з умовними змінними, оскільки рекурсивний м’ютекс може не звільнитися разом із початком очікування всередині wait, якщо він перед цим був зайнятий кілька разів (а це гарантує взаємне блокування).

Очікування виконання кількох умов

Можна організувати очікування виконання кількох умов, хоча це рекомендують робити тільки у разі необхідності, щоб не ускладнювати код. Для такого очікування потрібно використати одну умовну змінну й у циклі while перевіряти кількох умов:

//повинно виконуватися condition_expr1 або condition_expr2

while (! condition_expr1 && ! condition_expr2)

wait (condition, mutex);

// повинно виконуватися condition_expr1 і condition_expr2

while (! condition_expr1 || ! condition_expr2)

wait (condition, mutex);

Кожну умову треба сигналізувати окремо:

//виконують condition_expr1

signal (condition, mutex);

//…

//виконують condition_expr2

signal (condition, mutex);

 

Поняття монітора

Як ми бачимо, умовні змінні не використовують окремо від м’ютексів, причому є кілька правил взаємодії між цими примітивами. Ці правила є підґрунтям поняття монітора – синхронізаційної концепції вищого рівня.

Монітором називають набір функцій, які використовують один загальний м’ютекс і нуль або більше умовних змінних для керування паралельним доступом до спільно використовуваних даних відповідно до певних правил. Функції цього набору називають функціями монітора.

Ось правила, яких слід дотримуватися у разі реалізації монітора.

· Під час входу в кожну функцію монітора потрібно займати м’ютекс, під час виходу – звільняти. Отже, у кожний момент часу тільки один потік може перебувати всередині монітора (під яким розуміють сукупність усіх його функцій).

· Під час роботи з умовною змінною (і під час очікування, і під час сигналізації) необхідно завжди вказувати відповідний м’ютекс. Не можна працювати з умовними змінними, якщо м’ютекс незайнятий.

· Під час перевірки на виконання умови очікування потрібно використати цикл, а не умовний оператор.

Ідея монітора була вперше запропоновані в 1974 році відомим ученим у галузі комп’ютерних наук Ч.А. Хоаром. Монітор часто розуміють як високорівневу конструкцію мови програмування (як приклад такої мови звичайно наводять Java), а саме як набір функцій або методів класу, всередині яких автоматично зберігається неявний м’ютекс разом із операціями очікування і сигналізації. Насправді, як ми бачимо, концепція монітора може ґрунтуватися на базових примітивах – м’ютексах і умовних змінних – і не повинна бути обмежена якоюсь однією мовою.

Монітори Хоара відрізняються від тих, що були розглянуті тут (ці монітори ще називають MESA-моніторами за назвою мови, у якій вони вперше з’явилися). Головна відмінність полягає у реалізації сигналізації.

· У моніторах Хоара після сигналізації потік TS негайно призупиняють, і керування переходить до потоку TW, який при цьому захоплює блокування. Коли потік TW вийде із критичної секції або знову виконає операцію очікування, потік TS буде поновлено.

· У MESA-моніторах, як було видно, після сигналізації потік TS продовжує своє виконання, а потік TW просто переходить у стан готовності до виконання. Він зможе продовжити своє виконання, коли потік TS вийде з монітора (чекати цього доведеться недовго, тому що звичайно сигналізація відбувається наприкінці функції монітора).

Результатом є те, що для моніторів Хоара не обов’язково перевіряти умову очікування в циклі, досить умовного оператора (потік негайно отримує керування після виходу з очікування і не може статися так, що за цей час інший потік увійде в монітор і змінить умову). З іншого боку, ці монітори менш ефективні (потрібно витрачати час нате, щоб припиняти і поновлювати потік TS); потрібно мати повну гарантію того, що між виконанням сигналізації та передаванням керування потоку TW планувальник не передасть керування іншому потокові TX, який увійде у функцію монітора. Забезпечення такої гарантії потребує втручання в алгоритм роботи планувальника ОС.

Ці недоліки призводять до того, що на практиці використовують переважно MESA-монітори.

Ось приклад розв’язання задачі очікування завершення потоку із використанням монітора.

//всі функції перебувають у моніторі

//з кожним потоком пов’язана умовна змінна finished_cond

//і прапорець finished – спільно використовувані дані

void thread_init() {

mutex_lock(mutex);

//на початку виконання потоку умова не виконується

this_thread.finished = 0;

mutex_unlock(mutex);

}

void thread_exit() {

mutex_lock(mutex);

this_thread.finished = 1;

//розбудити потік, який очікує, якщо він є

signal(this_thread.finished_cond, mutex);

mutex_unlock(mute);

}

void thread_join(thread_t thread) {

mutex_lock(mutex);

//очікування закінчення потоку thread

while (! thread.finished)

wait(thread.finished_cond, mutex);

mutex_unlock(mutex);

}


Дата добавления: 2018-04-05; просмотров: 787; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!