- Ваша сильная сторона? - Multithreading - Вот 3 задачки. Сможете сделать до завтра?  - Я не могу решать столько задач одновременно Согласитесь, сoncurrency — одна из непростых тем программирования. В начале своей карьеры программиста кто‑то всячески пытается избежать погружения в эту тему, но рано или поздно приходится столкнуться с concurrency проблемами. Это может случиться, потому что нужно написать потокобезопасный код или прилетел баг на уже имеющийся код.  По неопытности некоторые могут просто замаскировать проблему, которая позже снова даст о себе знать. Некоторые из этих подходов распишу ниже. Но имейте в виду, это просто временное решение, которое на самом деле не решает проблему сoncurrency. Статья не про серебряную пулю, как исправить concurrency проблемы, а про костыльные подходы веселых и находчивых, которые не решают суть проблемы. Дело в том, что Sleep добавляют не только начинающие программисты. Мне встречались программисты, которые при опыте 3–5 лет работы делали такой фикс и в тестах кода, и в продакшене. Подобный код является по своей сути бомбой замедленного действия. Важно понять одно: если вы делаете фикc такого рода, он может быть замаскирован до поры до времени. Потом пройдёт обновление операционной системы или же вы поменяете железо на новое и все, тайминги изменятся и старые проблемы станут явными. Обратите внимание, увеличение времени sleep‑а — тоже не выход :) Порой обнаружение корня проблемы занимает много времени, поэтому программисты на практике часто добавляют логи для дальнейшего изучения проблемы, что правильно. Можно добавить немного логов — это действительно полезно и помогает решению проблемы. Но, бывает, добавляют лог‑сообщения через строчку. У вас там маленький кусок кода, обложенный кучей логов, и код чудесным образом перестает падать. Потом через какое‑то время поднимается история бага, и оказывается, что он не воспроизводился некоторое время. Поэтому баг закрывают по причине «Не воспроизводится N месяцев, возможно, уже пофиксили». А на деле баг остался.  Давайте разберемся, почему это пока «работает». В местах добавления логов код начинает выполняться медленнее и создаёт иллюзию, что рассинхрона нет и все «заработало», но ничего подобного. Нужно всегда помнить, input/output операции дорого стоят с точки зрения ресурсов системы. Оборачивать все в try‑catch конструкции вместо «нормального» фикса — тоже не выход. Осознанное использование этого подхода в продакшене я видела лишь однажды.  Дело было так. Жил‑был непотокобезопасный код много лет, который использовался в разных частях проекта. Время от времени появлялись креш‑дампы из‑за отсутствия средств синхронизации потоков в коде, который многие использовали как потокобезопасный. Со временем код стал устаревать, его начали заменять в проектах, и получил этот непотокобезопасный код статус «устаревший» и кандидат на удаление. И вот код уже встречается только в одном месте, креш‑дампы естественно продолжают появляться. Тикеты на проблему накапливаются, и менеджеры просят пофиксить проблему с условием минимальных затрат по времени. Переписывать тысячи строк кода, чтобы синхронизовать устаревший код, который удалят через 2–3 месяца, бессмысленно, только время потратишь. Решением категории «дёшево и сердито» оказывается обернуть соответствующие методы в try‑catch. Все понимают, что это корявое решение проблемы, но ничего не поделаешь, если желательно исправить сегодня. По факту, это даже не фикс, а маскирующий костыль. Делать подобное в поддерживаемом коде нельзя.  Бывает, какая‑то часть боевого кода или тест периодически падает. Быстро найти проблему не удается, да и проблема не совсем очевидная. Тут приходит гениальная мысль обернуть код в try‑catch, но не просто ловить исключения, а повторять падающий код несколько раз до победного конца. Такой подход напоминает русскую рулетку: выстрелит — не выстрелит. Результат выполнения кода вроде как улучается: количество падений уменьшается. Такой подход дает только временный эффект. Ведь реальная проблема не решена, и в какой‑то момент частота воспроизведения проблемы снова возрастет, и вы возвращаетесь к тому, с чего начали. Как ни крути, при разных подходах маскировки concurrency проблемы, ее все равно придется решать.   Программист