Page 261 - 6253
P. 261
рішення даної проблеми, що полягає у виклику методів такого класу в блоці
позначеного ключовим словом synchronized.
Коли потік входить у блок позначений словом synchronized, то він захоплює
блокування об’єкта obj.
synchronized (obj) { // синтаксис синхронізованого блоку
критична секція коду;
}
Іноді в коді зустрічаються спеціальні блокування схожі до наступного:
public class Bank {
private double[] accounts;
private Object lock = new Object();
...
public void transfer(int from, int to, int amount) {
synchronized (lock) { // спеціальне блокування
accounts[from] = accounts[from] - amount;
accounts[to] = accounts[to] + amount;
}
System.out.println();
}
}
В даному випадку об’єкт lock створюється тільки для використання
вбудованого блокування, яке є у кожного об’єкта в мові Java. Вбудованим
блокуванням об’єкта іноді користуються для реалізації додаткових атомарних
операцій. Така практика отримала назву клієнтського блокування. Розглянемо як
приклад клас Vector, методи якого є синхронізованими. А тепер припустимо, що
залишки на банківських рахунках зберігаються в об’єкті типу Vector<Double>.
Нижче наведена наївна реалізація методу transfer().
public void transfer(Vector<Double> accounts, int from,
int to, int amount) { // помилка!
accounts.set(from, accounts.get(from) - amount);
accounts.set(to, accounts.get(to) + amount);
System.out.println();
}
Методи get() та set() визначені в класі Vector є синхронізованими, проте, цілком
можливо, що потік буде призупинений на методі transfer() після завершення
першого виклику методу get(). Інший потік зможе записати будь-яке інше значення
260