Page 183 - 6571
P. 183
// очікувати
}
// перевести кошти
} finally {
bankLock.unlock();
}
}
Проте, що робити, якщо на рахунку немає достатньої
кількості коштів? Єдине рішення – це очікувати до того часу,
поки рахунок не буде поповнено під час виконання іншого
потоку. Проте, у представленому прикладі потік володіє
монопольним доступом до об’єкта bankLock, тому жоден інший
потік не в змозі виконати поповнення рахунку. Тому єдиним
правильним рішенням є використання умовного об’єкту.
З будь-яким об’єктом блокування може бути пов’язаний один
або декілька умовних об’єктів, які створюються за допомогою
фабричного методу newCondition(). Кожному умовному
об’єкту можна присвоїти ім’я, що буде асоціюватися з умовою,
яку він представляє. Наприклад, об’єкт, що представляє умову
«достатньо коштів», визначається наступним чином:
class Bank {
private Condition sufficientFunds;
...
public Bank() {
...
sufficientFunds = bankLock.newCondition();
}
}
Фабричний метод newCondition() повертає умовний
об’єкт, пов’язаний з відповідним блокуванням. Якщо під час
виконання методу transfer() буде виявлено, що коштів на
рахунку недостатньо, то він виконає виклик методу await(),
який переводить поточний потік в режим очікування, що дає
змогу поповнити рахунок в іншому потоці:
sufficientFunds.await();
Існує істотна відмінність між потоком, що очікує можливості
захопити блокування, і потоком, що викликав метод await().
Виклик методу await() переводить потік в режим очікування,
182