Інструкції synchronized Java

Інструкціїsynchronized дозволяють виконувати синхронізований код, який здатний блокувати довільний об'єкт, а не тільки поточний, або зменшити тривалість блокування, поширюючи її вплив лише на частину методу. Інструкція synchronized складається з двох частин – посилання на об'єкт, блокування якого запитується, та фрагмент коду, що виконується після З:1 хвата блокування. Загальна синтаксична форма synchronized -інструкції ви-

виразв результаті обчислення має давати об'єктне посилання. Після отримання права блокування виконується блок кодуІнструкції,після завершення якого блокування звільняється – блокування знімається навіть у тому випадку, коли всередині фрагмента кодуІнструкціївикидається виняток, що не піддається обробці. Оголошення synchronized -методу, розглянуте вище, - це, насправді, скорочена синтаксична конструкція для опису методу, тіло якого укладено всередину synchronized -інструкції, яка використовує для вказівки на блокований об'єкт посилання this.

Розглянемо метод, що передбачає заміну значення кожного елемента масиву абсолютною величиною та заснований на використанні інструкції synchronized, яка регулює доступ до масиву:

/** Присвоїти елементам цілого масиву абсолютні величини поточних значень */

public static void abs(int[] values)

Інструкція synchronized у тілі конструктора захоплює блокування об'єкта типу class для об'єкта Body точно так, як це робить статичний synchronized -метод класу. Було б неправильним використовувати для синхронізації посилання this, оскільки при кожному виклику конструктора вона вказує на різні об'єкти, тому блокування поточного (this) об'єкта не здатне запобігти можливості одночасногодоступу до nextID з кількох потоків. Також неправильно для отримання посилання на об'єкт типу class для поточного екземпляра використовувати метод Object. getclass - у розширеному класі, такому як AttributedBody, він поверне посилання на об'єкт class для AttributedBody, але не Body, і знову замість одного блокування буде створено кілька і одноразовий доступ до даних виявиться цілком можливим. Існує просте правило: завжди слід захищати статичні дані за допомогою блокування об'єкта типу class для класу, в якому ці дані оголошені.

У багатьох випадках для захисту коду замість інструкцій synchronized зручніше, проте використовувати synchronized -методи. (Наприклад, у класі Body ми могли б укласти код, який звертається до поля nextID, всередині статичного синхронізованого методу getNextID.) Відповісти на питання, коли застосовувати один підхід, а коли інший, вам допоможуть лише власні знання та практичний досвід.

Нарешті, здатність synchronized -інструкцій вимагати блокування довільних об'єктів уможливлює виконання синхронізації на стороні клієнта, як ми вже показали на прикладі статичного методу abs, що виконує заміну значень елементів масиву відповідними абсолютними величинами. Така здатність дуже важлива не тільки з точки зору захисту коду об'єктів, що не мають synchronized-методами, але й для синхронізації послідовностей звернень до об'єкта. Докладно ми розповімо про це у наступному розділі.

Джерело: Арнолд, Кен, Гослінг, Джеймс, Холмс, Девід. Мова програмування Java. 3-тє вид..: Пер. з англ. - М.: Видавничий дім "Вільямі", 2001. - 624 с. : іл. – Парал. тит. англ.