Page 264 - 6253
P. 264
розблокують призупинені потоки. Виклик методу wait() або notifyAll() рівнозначний
наступному коду:
buildConditional.await();
buildConditional.signalAll();
Отже, використання ключового слова synchronized дозволяє суттєво скоротити
вихідний код програми. В даному випадку, блокування керує потоками, які
намагаються увійти в метод synchronized, а умова керує потоками, що викликали
метод wait().
Поля та змінні типу volatile. Часто для захисту одного або двох полів класу від
асинхронного доступу потрібно синхронізувати доступ до усього об’єкта, що є
занадто затратною операцією в плані розподілу процесорного часу. Зрештою, що
може статися поганого під час асинхронних операцій запису або зчитування поля
екземпляру класу? На жаль, сучасні процесори і компілятори можуть бути джерелом
для появи великої кількості помилок під час таких нескладних операцій:
1. Комп’ютери з декількома процесорами можуть тимчасово утримувати
значення з пам’яті в регістрах або локальних кешах. Як наслідок, потокам, що
виконуються на різних процесорах, можуть бути доступні різні значення в одній і
тій же області пам’яті.
2. Компілятори можуть змінювати порядок виконання команд для досягнення
максимальної продуктивності програми. При цьому, результат виконання програми
жодним чином не міняється, але робиться припущення, що значення в пам’яті
змінюються тільки явними командами в коді. Проте, в багатопотоковій програмі
значення в пам’яті може бути змінено виконанням будь-якого потоку.
Ключове слово volatile використовується для встановлення неблокуючого
режиму синхронізованого доступу до поля класу. У випадку, коли поле класу
оголошене із модифікатором volatile, то компілятор і віртуальна машина враховують
той факт, що значення поля може бути паралельно модифіковане в іншому потоці.
Припустимо, що у класі визначено поле done типу boolean, значення якого
встановлюється в одному потоці і зчитується в іншому. Для синхронізації доступу
до даного поля можна використати механізм вбудованого блокування під час
проектування відповідного класу:
private boolean done;
263