В чём разница между синхронным и асинхронным кодом?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В чём разница между синхронным и асинхронным кодом?
Определение синхронного кода
Синхронный код выполняется линейно, по одной операции за раз. Каждая строка ждёт завершения предыдущей. Если операция занимает много времени (например, запрос к БД или сетевой вызов), весь поток выполнения блокируется, и последующий код не может выполняться до завершения текущей операции.
import time
import requests
def fetch_data():
print("Начинаю загрузку...")
response = requests.get("https://api.example.com/data") # Блокирует
print("Данные загружены")
return response.json()
start = time.time()
data = fetch_data()
print(f"Время: {time.time() - start}s")
Этот код ждёт сетевого запроса, и всё приложение заморожено в этот момент.
Определение асинхронного кода
Асинхронный код позволяет программе продолжить выполнение других задач, пока одна операция ждёт результата. Когда операция завершается, выполнение возобновляется с точки отложения. Это основано на концепции корутин и событийного цикла (event loop).
import asyncio
import aiohttp
async def fetch_data():
print("Начинаю загрузку...")
async with aiohttp.ClientSession() as session:
async with session.get("https://api.example.com/data") as response:
data = await response.json() # Не блокирует
print("Данные загружены")
return data
async def main():
start = asyncio.get_event_loop().time()
data = await fetch_data()
print(f"Время: {asyncio.get_event_loop().time() - start}s")
asyncio.run(main())
Ключевые различия
| Аспект | Синхронный | Асинхронный |
|---|---|---|
| Выполнение | Линейное, блокирующее | Неблокирующее, параллельное |
| Простота | Проще писать и понимать | Требует использования async/await |
| Производительность | Медленнее при I/O операциях | Быстрее при множественных I/O |
| Обработка ошибок | Стандартный try/except | try/except с async контекстом |
| Масштабируемость | Ограничена количеством потоков | Может обрабатывать тысячи операций |
Практический пример: параллельные запросы
Синхронно (медленно):
import requests
import time
def sync_fetch_multiple():
urls = ["url1", "url2", "url3"]
start = time.time()
for url in urls:
response = requests.get(url)
print(f"Загружен: {url}")
print(f"Всего время: {time.time() - start}s") # ~9 сек (3 сек × 3)
sync_fetch_multiple()
Асинхронно (быстро):
import asyncio
import aiohttp
import time
async def async_fetch_multiple():
urls = ["url1", "url2", "url3"]
start = time.time()
async with aiohttp.ClientSession() as session:
tasks = [session.get(url) for url in urls]
await asyncio.gather(*tasks)
print(f"Всего время: {time.time() - start}s") # ~3 сек (параллельно)
asyncio.run(async_fetch_multiple())
Когда использовать каждый подход
Синхронный код подходит когда:
- Операции быстрые (вычисления в памяти)
- Нет множественных I/O операций
- Простота кода важнее производительности
- Разработка скриптов и инструментов
Асинхронный код нужен когда:
- Много сетевых запросов
- Веб-приложения с высокой нагрузкой
- Необходима высокая параллельность
- Работа с БД, API, файлами
Event Loop - сердце асинхронности
Асинхронный код работает благодаря event loop (событийному циклу). Это основной механизм, который:
- Запускает корутину
- Когда встречает
await, приостанавливает её - Запускает другие корутины
- Когда данные готовы, возобновляет первую корутину
async def main():
# Event loop управляет выполнением этих операций
result1 = await operation1()
result2 = await operation2()
return result1, result2
asyncio.run(main()) # Запускает event loop
Заключение
Синхронный код — это последовательное выполнение, где каждая операция ждёт завершения предыдущей. Асинхронный код позволяет программе продолжать работу, пока одна операция ждёт, что значительно повышает производительность при работе с I/O операциями. Выбор между ними зависит от требований проекта и специфики задачи.