Page 256 - 6253
P. 256
тобто стати меншим дозволеної межі. Тому необхідно певним чином гарантувати,
що жодний інший потік не зможе змінити залишок на рахунку між його перевіркою
і переказом коштів. Для цього потрібно захистити як перевірку залишку на рахунку,
так і сам переказ коштів, що можна зробити за допомогою наступного рішення:
public void transfer(int from, int to, int amount) {
bankLock.lock();
try {
while (accounts[from] < amount) {
// очікувати
}
// перевести кошти
} finally {
bankLock.unlock();
}
}
Проте, що робити, якщо на рахунку немає достатньої кількості коштів? Єдине
рішення – це очікувати до того часу, поки рахунок не буде поповнено під час
виконання іншого потоку. Проте, у представленому прикладі потік володіє
монопольним доступом до об’єкта bankLock, тому жоден інший потік не в змозі
виконати поповнення рахунку. Тому єдиним правильним рішенням є використання
умовного об’єкту.
З будь-яким об’єктом блокування може бути пов’язаний один або декілька
умовних об’єктів, які створюються за допомогою фабричного методу
newCondition(). Кожному умовному об’єкту можна присвоїти ім’я, що буде
асоціюватися з умовою, яку він представляє. Наприклад, об’єкт, що представляє
умову «достатньо коштів», визначається наступним чином:
class Bank {
private Condition sufficientFunds;
...
public Bank() {
...
sufficientFunds = bankLock.newCondition();
}
}
Фабричний метод newCondition() повертає умовний об’єкт, пов’язаний з
255