Застосування synchronized - 1

— Привіт, Аміго!

— Так, тут я, тут.

— Сьогодні я розповім тобі про практичне застосування synchronized.

Коли у програмі багато об'єктів та ниток, то часто трапляються ситуації, коли з одним об'єктом одночасно працює кілька ниток. Нитки при цьому заважають одна одній.

— Так, я це вже знаю.

— Так от, припустимо, у тебе є об'єкт, до якого звертаються кілька ниток. Щоб з ним не було проблем, можна зробити дві речі.

Перша – всі місця роботи з цим об'єктом обернути на блоки synchronized. Але такий підхід може не спрацювати, якщо якийсь програміст у своєму коді звертатиметься до об'єкта безпосередньо, без блоку synchronized.

Тому найчастіше застосовується другий підхід – об'єкт роблять ниткобезпечним (thread-safe). Тобто. механізм synchronized вбудовують у сам об'єкт – оголошують його методи synchronized та/або обертають код усередині методів блоки synchronized.

— Тобто всі об'єкти, які можуть використовуватися з різних ниток, а це майже всі об'єкти програми, я маю зробити thread-safe?

— Загалом, так. Насправді, не всі об'єкти програми використовуються з різних ниток, але зазвичай багато. Отже, коли ти починаєш писати код своєї нитки і в ній звертаєшся до різних об'єктів своєї програми, то при викликі кожного методу, ти повинен задуматися – а чи безпечний цей виклик?

— Безпечний?

— Безпечний (thread-safe) — це безпечно під час виклику з різних ниток.

Ось тобі кілька прикладів. Допустимо, у тебе є об'єкт String, до якого відбувається звернення з різних ниток. Як ти вже повинен був запам'ятати, String (і всі інші типові типи) є immutable. А це означає, що після створення об'єкт не змінюється. Отже, і «зламати» такий об'єкт не можна. Всі immutable об'єкти є thread-safe.

— Вже легше.

— Тепер, припустимо, тобі потрібний рядок, що змінюється.

— Ага, пам'ятаю. Є два види таких рядків – StringBuffer та StringBuilder. StringBuffer - це аналог StringBuilder, але у нього всі методи синхронізовані. Він також є thread-safe?

— Так. Якщо тобі потрібно звертатися до об'єкта StringBuilder з різних ниток, то потрібно замінити його на StringBuffer, інакше рано чи пізно нитки змінюватимуть його одночасно і «поломають».

— А якщо об'єкт, якого відбувається звернення з різних ниток, – це об'єкт мого власного класу? Мені також треба додавати до його методів synchronized?

— Так. Найкраще керуватися таким правилом – усі об'єкти, до яких відбувається звернення з різних ниток, мають бути thread-safe.

— Зрозуміло. Не думав, що так серйозно. Дякую, Еллі.

— Будь ласка. Сподіваюся, ці поради допоможуть тобі, коли Дієго дасть тобі пару своїх легких завдань ☺