Page 189 - 6571
P. 189

В  даному  випадку  об’єкт  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().  Інший  потік  зможе  записати  будь-яке

            інше  значення  на  ту  ж  саму  позицію.  Тому,  для  захоплення
            блокування можна використати наступний підхід:

                  public void transfer(Vector<Double> accounts, int from,
                                  int to, int amount) {
                    synchronized (accounts) {
                      accounts.set(from, accounts.get(from) - amount);
                      accounts.set(to, accounts.get(to) + amount);
                    }
                    System.out.println();
                  }

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

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

            не рекомендується до застосування.


                  20.2 Керування міжпотоковими комунікаціями


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

                                                        188
   184   185   186   187   188   189   190   191   192   193   194