Обложка: Зачем нужно знать многопоточную разработку, даже если вы не собираетесь с ней работать

Зачем нужно знать многопоточную разработку, даже если вы не собираетесь с ней работать

Юрий Бабак

Юрий Бабак

руководитель разработки фронт-офисных решений в Национальной системе платежных карт

На последнем Joker у меня был разговор с коллегами из JUG’а на тему: «Все спрашивают про многопоточку, а задач с ней нет и научиться на практике негде». На самом деле, многопоточка есть почти всегда, особенно в Java-мире. Даже если нет никаких задач с ней явно связанных, почти всегда код будет работать в многопоточном окружении.

Меня зовут Юрий Бабак. Более десяти лет я занимаюсь разработкой на Java, а сейчас возглавляю команду разработки фронт-офисных решений в Национальной системе платежных карт (Мир Plat.form). И в этой статье я хочу рассказать, как эта скрытая сложность может догнать любого разработчика и что ему с этим делать.

Личная история

Опыт работы с многопоточной — часто это вопрос интереса, любознательности. Например, пишешь ты обработку запроса в сервлете. Вроде бы просто, скучно, понятно. Один запрос, один ответ, напиливаешь какую-то бизнес-логику или и того хуже, баги в этом правишь. И, казалось бы, причем тут конкурентная обработка? С одной стороны, это верно, не подкопаешься. А с другой это же сервер, тут десятки-сотни-тысячи одновременных запросов, сервак управляет жизненным циклом приложения, на низком уровне принимает запросы и отдает ответы в высоко конкурентном окружении. И это мы ещё не спускаемся на уровень JVM, ОС и ниже.

Java — достаточно выразительный язык разработки с огромным количеством фреймворков, которые скрывают всю сложность от разработчика. И возможна ситуация, когда, занимаясь разработкой лет десять, можно ни разу не столкнуться с многопоточным кодом, а он все равно есть, пусть и скрыт за реализацией внешних API. И это даже нормально, особенно в каком-нибудь enterprise.

Но дальше есть, скажем так, развилка. Можно спокойно пилить задачи, закрывать тикеты и быть молодцом. А можно копать и изучать, что же там, под капотом. Я давно слышу, что современные разработчики примерно в такой же ситуации, как и Алиса в зазеркалье. Чтобы просто оставаться на месте, надо бежать со всех ног. И ещё больше надо делать, чтобы продвигаться вперед. Согласны?

Почему без этого плохо

Но если все закрыто фреймворками, то зачем об этом вообще думать?

И тут вспоминается история, которая произошла недавно. И сразу спойлер — если бы разработчик держал в фокусе, что он работает в многопоточном окружении, то сэкономил бы несколько дней разработки.

Итак, у этого разработчика было время поработать над ускорением прохождения пакета регрессионных тестов. И для этого подключили несколько окружений и сменили систему журналирования логов на асинхронную.

И локально все работало отлично, а на стенде регресс начал разваливаться, причем делал это самым непредсказуемым образом. Разные сценарии, в разных местах, ещё и не регулярно.

Разработчик потратил один день, решил разобраться, углубиться. Прошел второй день, на третий — мы решили ему помочь. Оказалось, проблема именно в журналировании. Из-за изменения механизма на асинхронный, возникали гонки с бизнес-логикой, которая не предполагала асинхронное изменение сообщения во время обработки. В одном потоке могли происходить изменения состояния, пока объект был в очереди на запись в сокет.

И классно, что это был рефакторинг, а не хотфиксы перед выходом важного релиза. История, о которой я рассказал выше – не уникальна. Она может возникнуть в том или ином виде в любом проекте.

Таким образом, мы все равно работаем в многопоточном окружении, даже если этого не осознаем. Получается, даже в таком варианте можно выстрелить себе в ногу, если не думать о неочевидных побочных эффектах.

А делать-то что?

Допустим, надо знать многопоточку. Если повезло, и есть боевые задачи, то все хорошо. Но что делать, если их нет?

Лично мои рекомендации:

  • прочитать JCIP, можно два раза;
  • придумать себе проект на неделю-две, например, написать собственный веб-сервер на голой Java (или на C/go/ваш любимый язык);
  • классные тестовые тоже подходят;
  • пойти под капот фреймворков из боевых проектов, смотреть как они устроены, профилировать их.

Любой из этих пунктов уже даст больше опыта, чем обычно есть у людей, не занимающихся системной разработкой.

А как думаете вы, будет ли это полезным или у вас есть свой способ?