Page 260 - 6571
P. 260

внішніх методів (наприклад, з використанням оператора synch-
                  ronized);
                        4) потоки не блокуються в очікуванні звільнення монітора.

                        Припустимо, що у класі визначено поле done типу boole
                  n, значення якого встановлюється в одному потоці і зчитується в

                  іншому. Для синхронізації доступу до даного поля можна вико-
                  ристати механізм вбудованого блокування під час проектування
                  відповідного класу:

                        private boolean done;
                        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; // не атомарна операція
                        }

                        Ще одним із варіантів отримати надійний доступ до спільно-
                  го поля з декількох потоків є використання ключового поля fin-
                  al. Значення поля оголошеного з модифікатором final, не мо-

                  же  бути  змінене  після  його  ініціалізації.  Фінальні  поля  об’єкта
                  ініціалізуються в його конструкторі. Якщо конструктор відпові-
                  дає певним простим правилам (посилання this не повинне по-

                  кинути  конструктор  до  його завершення),  то  коректне  значення
                  поля  оголошеного  з  модифікатором  final  буде  видимим  для
                  інших потоків без синхронізації. Розглянемо наступний рядок коду:

                                                             259
   255   256   257   258   259   260   261   262   263   264   265