Page 192 - 6571
P. 192

компілятори можуть бути джерелом для появи великої кількості
                  помилок під час таких нескладних операцій:
                        1. Комп’ютери з декількома процесорами можуть тимчасово
                  утримувати значення з пам’яті в регістрах або локальних кешах.

                  Як  наслідок,  потокам,  що  виконуються  на  різних  процесорах,
                  можуть  бути  доступні  різні  значення  в  одній  і  тій  же  області
                  пам’яті.

                        2.  Компілятори  можуть  змінювати  порядок  виконання
                  команд  для  досягнення  максимальної  продуктивності  програми.
                  При  цьому,  результат  виконання  програми  жодним  чином  не
                  міняється,  але  робиться  припущення,  що  значення  в  пам’яті

                  змінюються  тільки  явними  командами  в  коді.  Проте,  в
                  багатопотоковій програмі значення в пам’яті може бути змінено

                  виконанням будь-якого потоку.
                        Ключове          слово         volatile           використовується              для
                  встановлення  неблокуючого  режиму  синхронізованого  доступу
                  до  поля  класу.  У  випадку,  коли  поле  класу  оголошене  із

                  модифікатором  volatile,  то  компілятор  і  віртуальна  машина
                  враховують  той  факт,  що  значення  поля  може  бути  паралельно
                  модифіковане в іншому потоці.

                        Припустимо, що у класі визначено поле done типу boolean,
                  значення  якого  встановлюється  в  одному  потоці  і  зчитується  в
                  іншому.  Для  синхронізації  доступу  до  даного  поля  можна

                  використати  механізм  вбудованого  блокування  під  час
                  проектування відповідного класу:

                        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; }

                                                             191
   187   188   189   190   191   192   193   194   195   196   197