Page 255 - 6253
P. 255
продовжити своє виконання. Усе це дає змогу гарантувати, що загальний баланс на
рахунку в даному випадку буде завжди залишатись сталим.
Проте, потрібно мати на увазі, що у кожного об’єкта типу Bank є свій власний
об’єкт типу ReentrantLock. Якщо два потоки спробують звернутися до одного і того
ж об’єкту типу Bank, то один із них буде заблоковано. Але якщо два потоки
звертаються до різних об’єктів типу Bank, то кожен із них отримає своє блокування і
жоден з потоків при цьому не буде заблокованим, оскільки кожен із них працює з
своїм екземпляром класу Bank.
Описаний вище вид блокування називається реентерабельним, оскільки потік
може повторно захоплювати блокування, яким він уже володіє. Для кожного
блокування передбачений лічильник захоплень, що відслідковує вкладені виклики
методу lock(). Кожен виклик методу lock() в потоці повинен супроводжуватися
подальшим викликом методу unlock(), з метою зняття блокування. Завдяки такому
підходу, із захищеного блоку коду існує можливість викликати інші методи, що
використовують те ж саме блокування.
Досить часто потік, що увійшов в критичну секцію коду не може продовжити
свого виконання, оскільки не була задоволена певна умова. Тому для керування
потоками, що захопили блокування, але не можуть виконати жодних дій,
використовуються умовні об’єкти. Також, згідно певних історичних причин умовні
об’єкти нерідко називаються умовними змінними.
Спробуємо удосконалити розглянуту раніше програму імітацію банку. Не
будемо виконувати переміщення коштів з рахунку, якщо на ньому не має достатньої
суми, щоб покрити витрати на переказ. Проте код, що представлено нижче не зовсім
підходить для перевірки даної умови:
if (bank.getBalance(from) >= amount)
bank.transfer(from, to, amount);
Адже цілком ймовірно, що поточний потік призупинить своє виконання в
проміжку між успішним виконанням перевірки умови і викликом методу transfer():
if (bank.getBalance(from) >= amount)
// потік може призупинити своє виконання в цьому місці коду
bank.transfer(from, to, amount);
На момент відновлення роботи потоку залишок на рахунку може змінитися,
254