Page 261 - 6253
P. 261

рішення  даної  проблеми,  що  полягає  у  виклику  методів  такого  класу  в  блоці

            позначеного ключовим словом synchronized.

                  Коли  потік  входить  у  блок  позначений  словом  synchronized,  то  він  захоплює

            блокування об’єкта obj.

                  synchronized (obj) { // синтаксис синхронізованого блоку
                     критична секція коду;
                  }

                  Іноді в коді зустрічаються спеціальні блокування схожі до наступного:

                  public class Bank {
                     private double[] accounts;

                     private Object lock = new Object();
                     ...
                     public void transfer(int from, int to, int amount) {

                        synchronized (lock) { // спеціальне блокування
                           accounts[from] = accounts[from] - amount;
                           accounts[to] = accounts[to] + amount;

                        }
                        System.out.println();

                     }
                  }
                  В  даному  випадку  об’єкт  lock  створюється  тільки  для  використання

            вбудованого  блокування,  яке  є  у  кожного  об’єкта  в  мові  Java.  Вбудованим

            блокуванням  об’єкта  іноді  користуються  для  реалізації  додаткових  атомарних

            операцій.  Така  практика  отримала  назву  клієнтського  блокування.  Розглянемо  як

            приклад  клас  Vector,  методи  якого  є  синхронізованими.  А  тепер  припустимо,  що

            залишки  на  банківських  рахунках  зберігаються  в  об’єкті  типу  Vector<Double>.

            Нижче наведена наївна реалізація методу transfer().


                  public void transfer(Vector<Double> accounts, int from,
                                          int to, int amount) { // помилка!
                     accounts.set(from, accounts.get(from) - amount);
                     accounts.set(to, accounts.get(to) + amount);

                     System.out.println();
                  }

                  Методи get() та set() визначені в класі Vector є синхронізованими, проте, цілком

            можливо,  що  потік  буде  призупинений  на  методі  transfer()  після  завершення

            першого виклику методу get(). Інший потік зможе записати будь-яке інше значення


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