— Привет, Амиго!
— Да тут я, тут.
— Сегодня я расскажу тебе о практическом применении 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.
— Ясно. Не думал, что все так серьезно. Спасибо, Элли.
— Пожалуйста. Надеюсь, эти советы помогут тебе, когда Диего даст тебе пару своих легких задач ☺
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ