Page 258 - 6253
P. 258
змінюються залишки на рахунках, потокам що перебувають в стані очікування слід
надавати чергову можливість для перевірки цих залишків. У представленому нижче
прикладі метод signalAll() викликається під час завершення переказу коштів.
public void transfer(int from, int to, int amount) {
bankLock.lock();
try {
while (accounts[from] < amount)
sufficientFunds.await();
// переказати кошти
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}
Слід також мати на увазі, що виклик методу signalAll() не спричиняє негайну
активацію призупиненого потоку. Він лише розблокує потоки, що перебувають в
стані очікування, щоб вони мали можливість змагатися за об’єкт блокування.
Існує також метод signal(), який розблокує тільки один потік із тих що
перебувають в очікуванні, вибираючи його при цьому випадковим чином. Це більш
ефективно, ніж розблоковувати всі заблоковані потоки, хоча в даному випадку існує
певна небезпека. Якщо випадково обраний потік виявить, що ще не може
продовжити свого виконання, то він знову перейде в режим очікування. І якщо
жодний інший потік не викличе знову метод signal(), то система перейде в стан
взаємного блокування.
Отже, підведемо короткі підсумки, перерахувавши ключові моменти, що
стосуються блокувань та умов:
1. Блокування захищають критичні секції коду, дозволяючи при цьому
виконувати даний код тільки одному потоку в конкретний момент часу.
2. Блокування використовуються для керування потоками, які намагаються
увійти в захищену секцію коду.
3. Кожен умовний об’єкт керує потоками, які увійшли в захищену секцію коду,
але поки що не в змозі продовжити своє виконання.
257