Page 265 - 6253
P. 265
public synchronized boolean isDone() { return done; }
public synchronized void setDone() { done = true; }
Проте, можливо використання вбудованого блокування є не найкращою ідеєю.
Адже методи isDone() та setDone() можуть виявитися заблокованими, якщо інший
потік заблокував об’єкт відповідного класу. Інший варіант полягає у використанні
для поля done об’єкту типу Lock. Проте, у цьому випадку потрібно написати багато
рутинного коду, тому є зміст оголосити поле done з модифікатором volatile як це
зроблено нижче:
private volatile boolean done;
public boolean isDone() { return done; }
public void setDone() { done = true; }
Під час роботи із змінними типу volatile не гарантується жодна атомарність
операцій. Наприклад, наведений нижче метод не гарантує зміни значення поля done
на протилежне.
public void flipDone() {
done =! done; // не атомарна операція
}
Поля та змінні типу final. Ще одним із варіантів отримати надійний доступ до
спільного поля з декількох потоків є використання ключового поля final. Розглянемо
наступний рядок коду:
final Map accounts = new HashMap();
Змінна accounts стане доступною для інших потоків після виконання
конструктора HashMap(). Якщо не оголосити її із модифікатором final, то немає
жодної гарантії, що оновлене значення змінної accounts виявиться доступним з
інших потоків. Якщо виконання конструктора класу HashMap буде перервано іншим
потоком, то значення змінної accounts може виявитися рівним null. Проте, потрібно
також розуміти, що використання модифікатора final під час створення об’єкта не
робить операції над ним потокобезпечними. Якщо стан об’єкта змінюється та
зчитується в декількох потоках, то як і раніше необхідна його синхронізація.
10.5.3 Атомарність операцій та потокобезпечні колекції
Спільні змінні можуть бути оголошені як volatile, тільки за умови, що над ними
не виконується жодних інших операцій, окрім присвоєння. У пакеті
264