Page 247 - 6571
P. 247

Захист  блоку  коду  засобами  класу  ReentrantLock  в  за-
            гальному випадку виглядає наступним чином:

                  private Lock bankLock = new ReentrantLock();
                  public void transfer(){
                     try {
                        bankLock.lock();
                        // критична секція коду
                     } finally {
                        //  зняти  блокування,  навіть  у  випадку  генерації
            винятку
                        bankLock.unlock();
                     }
                  }

                  Дана конструкція гарантує, що тільки один потік в конкрет-

            ний момент часу зможе увійти в критичну секцію коду. Як тільки
            потік заблокує об’єкт блокування, то жоден інший потік не зможе
            виконати виклик методу lock() оскільки під час спроби це зро-

            бити вони будуть дезактивовані доти, поки перший потік не зніме
            блокування  з  об’єкта  блокування.  Також,  дуже  важливо
            розмістити виклик методу unlock() у блоці finally, оскільки

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

            жди.
                  Проте,  потрібно  мати  на  увазі,  що  у  кожного  об’єкта  типу
            Bank є свій власний об’єкт типу ReentrantLock. Якщо два по-

            токи  спробують  звернутися  до  одного  і  того  ж  об’єкту  типу
            Bank,  то  один  із  них  буде  заблоковано.  Але  якщо  два  потоки

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

            класу Bank.
                  Описаний  вище  вид  блокування  називається  реентерабель-
            ним,  оскільки  потік  може  повторно  захоплювати  блокування,

            яким  він  уже  володіє.  Для  кожного  блокування  передбачений
            лічильник  захоплень,  що  відслідковує  вкладені  виклики  методу
            lock().





                                                        246
   242   243   244   245   246   247   248   249   250   251   252