Page 193 - 6571
P. 193

Під  час  роботи  із  змінними  типу  volatile  не  гарантується
            жодна атомарність операцій. Наприклад, наведений нижче метод
            не гарантує зміни значення поля done на протилежне.

                  public void flipDone() {
                    done =! done; // не атомарна операція
                  }

                  Поля та змінні типу final. Ще одним із варіантів отримати
            надійний  доступ  до  спільного  поля  з  декількох  потоків  є

            використання  ключового  поля  final.  Розглянемо  наступний
            рядок коду:

                  final Map accounts = new HashMap();

                  Змінна accounts стане доступною для інших потоків після
            виконання  конструктора  HashMap().  Якщо  не  оголосити  її  із

            модифікатором  final,  то  немає  жодної  гарантії,  що  оновлене
            значення  змінної  accounts  виявиться  доступним  з  інших
            потоків.  Якщо  виконання  конструктора  класу  HashMap  буде

            перервано іншим потоком, то значення змінної accounts може
            виявитися  рівним  null.  Проте,  потрібно  також  розуміти,  що

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



                  20.3 Атомарність операцій та потокобезпечні колекції


                  Спільні змінні можуть бути оголошені як volatile, тільки
            за умови, що над ними не виконується жодних інших операцій,

            окрім  присвоєння.  У  пакеті  java.util.concurrent.atomic
            визначено цілий ряд класів, в яких ефективно використовуються
            команди машинного рівня, що гарантують атомарність операцій

            відмінних  від  присвоєння,  без  використання  блокувань.
            Наприклад,  в  класі  AtomicInteger  визначено  методи
            incrementAndGet()  та  decrementAndGet(),  які  здійснюють

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





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