Page 254 - 6253
P. 254
myLock.unlock();
}
Дана конструкція гарантує, що тільки один потік в конкретний момент часу
зможе увійти в критичну секцію коду. Як тільки потік заблокує об’єкт блокування,
то жоден інший потік не зможе виконати виклик методу lock() оскільки під час
спроби це зробити вони будуть дезактивовані доти, поки перший потік не зніме
блокування з об’єкта блокування. Також дуже важливо розмістити виклик методу
unlock() у блоці finally, оскільки блокування має бути знято навіть у випадку, якщо
під час виконання коду з критичної секції буде згенеровано виняток. В іншому
випадку інші потоки залишаться заблокованими назавжди.
Виконаємо блокування для захисту критичної секції коду з методу transfer() що
визначений у класі Bank.
public class Bank {
// об’єкт класу ReentrantLock, реалізує інтерфейс Lock
private Lock bankLock = new ReentrantLock();
...
public void transfer(int from, int to, int amount) {
bankLock.lock();
try {
System.out.print(Thread.currentThread());
accounts[from] = accounts[from] - amount;
System.out.printf("%10.2f з %d до %d", amount,
from, to);
accounts[to] = accounts[to] + amount;
System.out.printf("Загальний баланс: %10.2f%n",
getTotalBalance());
} finally {
bankLock.unlock();
}
}
}
Припустимо, що в одному із потоків викликається метод transfer() і даний потік
призупиняється під час його виконання. Припустимо також, що в цей момент
другий потік також викликає метод transfer(), проте, він буде дезактивований і
змушений очікувати, поки виконання методу transfer() не завершиться в першому
потоці. І тільки тоді, коли перший потік зніме блокування, другий потік зможе
253