Синхронное, асинхронное, конкурентное и параллельное выполнение — в чём разница простыми словами
В чём разница и почему это важно
Разработчики любят использовать термины из названия, которые для них звучат естественно, но для большинства людей не связанных с разработкой эти термины могут пониматься совсем иначе. Этот текст — для всех, кому приходится взаимодействовать с разработкой и тех плохо понимает разницу между терминами.
После прочтения вы будете чётко понимать разницу между синхронным, асинхронным, конкурентным и параллельным выполнением — и почему эти различия имеют практическое значение.
Как ускорить выполнение
Если хочется, чтобы программа или сайт работали быстрее, вариантов на самом деле не так много.
Можно купить более мощное железо.
Можно делать меньше — сократить функциональность или упростить бизнес-логику.
Можно использовать более эффективные алгоритмы.
Можно выполнять задачи параллельно, задействуя несколько ядер процессора.
И можно сокращать время ожидания/отклика.
Последний пункт часто недооценивают, хотя именно он даёт наибольший эффект во многих системах.
Асинхронность и ожидание
Рассмотрим простой бытовой пример — стирку.
Сортировка вещей перед стиркой занимает 15 минут.
Сама стирка длится 40 минут.
Развесить и разложить чистое — ещё около 10 минут.
Если делать всё строго последовательно, процесс выглядит так: сначала сортируем вещи, затем запускаем стирку и просто ждём, после чего разбираем чистое. В сумме получается 65 минут.
Но ключевой момент в том, что стирка не требует вашего участия. Вы можете запустить машину и заняться другими делами — разобрать почту, приготовить ужин, навести порядок. Машина работает, а вы не тратите время на ожидание.
Именно так асинхронность сокращает общее время. Работа не становится быстрее сама по себе, но исчезают паузы, в которые ничего не происходит.
Если часть действий выполняется параллельно — например, вдвоем — реальное время сокращается ещё сильнее. При этом суммарное количество затраченных человеко-минут может даже увеличиться, но результат будет получен раньше.
Здесь важно различать два понятия: есть время выполнения (сколько усилий было потрачено в сумме), и есть реальное время — сколько прошло от начала до конца.
Последовательное, конкурентное и параллельное выполнение
Последовательная модель выполняет задачи строго шаг за шагом.
Параллельная — действительно выполняет их одновременно.
Между ними есть ещё одна модель — конкурентная, или чередующаяся.
Представим задачу, сильно нагружающую процессор, например распаковку большого архива. Если бы система работала строго последовательно, на время распаковки она бы полностью «зависла»: нельзя было бы открыть браузер или даже передвинуть курсор.
На практике этого не происходит. Система периодически приостанавливает распаковку, чтобы дать процессорное время другим задачам — обработке ввода, интерфейсу, фоновым процессам. Затем возвращается к распаковке.
Задачи не выполняются одновременно, но они чередуются. Их выполнение перекрывается по времени, и система остаётся отзывчивой.
Такое выполнение обеспечивается конкурентными потоками. В повседневной речи термины «конкурентное» и «чередующееся» часто используют как синонимы.
Исходящие запросы: синхронно и асинхронно
Представим веб-краулер — программу, которая обходит сайт целиком. Она загружает страницу, извлекает контент и ссылки, затем повторяет этот процесс для каждой найденной ссылки.
Основная проблема здесь не в вычислениях, а в ожидании сети. Каждая страница может загружаться доли секунды, но при большом количестве страниц эти задержки накапливаются в минуты и часы.
Пока данные не получены, выполнение просто «стоит». Процессор при этом простаивает.
Асинхронный вариант выглядит иначе. Здесь, пока идёт ожидание ответа от сети, система может выполнять другие задачи. Это требует дополнительных усилий при разработке, но даёт серьёзный прирост производительности, если узкое место — ввод-вывод.
Входящие запросы: синхронно и асинхронно
Теперь посмотрим на ситуацию со стороны сервера.
Пользователь отправляет запрос, сервер собирает данные — из базы, из внешних сервисов — и возвращает ответ. Каждый такой шаг занимает время, и пользователей обычно много.
Самая простая модель — обрабатывать запросы строго по очереди. Но если первый запрос выполняется несколько секунд, остальные будут просто ждать.
Обычно проблему пытаются решить запуском нескольких потоков или процессов. Но их количество ограничено, и при большом числе одновременных запросов перестаёт масштабироваться.
Ключевое наблюдение в том, что сервер чаще всего не упирается в процессор. Он ждёт данные — от базы данных или других сервисов — и в это время ничего полезного не делает.
Асинхронная модель позволяет задаче, которая ждёт ответа, временно уступить выполнение другим задачам. В итоге сервер может обрабатывать значительно больше одновременных запросов, сокращая общее время ожидания для пользователей. Эффект особенно заметен при высокой нагрузке.