Page 255 - 6571
P. 255
конання методу transfer() буде виявлено, що коштів на раху-
нку недостатньо, то він виконає виклик методу await(), який
переводить поточний потік в режим очікування, що дає змогу по-
повнити рахунок в іншому потоці.
while (account - amount < 0) {
sufficientFunds.await();
}
Існує істотна відмінність між потоком, що очікує можливості
захопити блокування, і потоком, що викликав метод await().
Виклик методу await() переводить потік в режим очікування,
визначений для даної умови. Потік залишається в режимі очіку-
вання доти, поки інший потік не викличе метод signalAll()
по тій же умові очікування.
sufficientFunds.signalAll();
При цьому, планувальник потоків переводить усі потоки, що
задовольняють умові очікування в активний стан, і як тільки
об’єкт блокування стане доступним, один з цих потоків захопить
його і продовжить своє виконання з того місця, де він був призу-
пинений, отримавши керування після виклику методу await().
Також важливо, щоб метод signalAll() був викликаний в
будь-якому іншому потоці, відмінному від потоку, що виконав
виклик метода await(), оскільки він не має можливості повто-
рно активізувати самого себе. Якщо жоден із потоків не «подбає»
про повторну активацію призупиненого потоку, то його виконан-
ня ніколи не відновиться, що може призвести до так званого вза-
ємного блокування. Якщо всі інші потоки будуть заблоковані, а
метод await() буде викликаний з останнього активного потоку
без попередньоговиклику методу signalAll(), то даний потік
також виявиться заблокованим.
Існує також метод signal(), який розблокує тільки один
потік із тих що перебувають в очікуванні, вибираючи його при
цьому випадковим чином. Це більш ефективно, ніж розблокову-
вати всі заблоковані потоки, хоча в даному випадку існує певна
небезпека. Якщо випадково обраний потік виявить, що ще не мо-
же продовжити свого виконання, то він знову перейде в режим
очікування. І якщо жодний інший потік не викличе знову метод
signal(), то система перейде в стан взаємного блокування.
254