IT "Понятно"
Обучение для начинающих
c 8 лет и до бесконечности


Что такое синхронный и асинхронный код?

Что такое синхронный и асинхронный код?

Опубликовано: 10.04.2024

Синхронный и асинхронный классифицируют два разных стиля программирования, каждый со своими преимуществами и недостатками. А какая будет разница между ними? Давайте разбираться


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

Примером синхронного кода в Python может служить следующий фрагмент, который содержит цикл while, обрабатывающий список элементов:

items = [1, 2, 3, 4, 5]

for item in items:

    print(item)

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

Выполнение синхронного кода может занять много времени и может вызвать проблемы с производительностью, особенно когда код выполняет блокирующие операции, такие как чтение и запись файлов, обращение к сети, или поиск значений в базе данных. Для решения этой проблемы в Python используют асинхронное программирование с использованием конструкций async/await и библиотеки asyncio. Они позволяют выполнять несколько задач асинхронно, не блокируя выполнение других задач, и добиваться более высокой производительности.

Асинхронный код — это подход к написанию кода, который позволяет выполнять несколько задач одновременно в рамках одного процесса. Это достигается за счет использования асинхронных функций (корутин). В отличие от синхронного кода, который выполняет каждую задачу последовательно, синхронный код может запустить несколько задач "параллельно" и организовать их выполнение с помощью итераций и вызовов коллбеков.

Примером использования асинхронного кода является библиотека asyncio в Python.

Например, вот простой пример кода, который использует asyncio для запуска
нескольких задач одновременно и ожидания их завершения:

import asyncio

async def count_to_three():

    print("Веду отсчёт. 1")

    await asyncio.sleep(0)

    print("Веду отсчёт. 2")

    await asyncio.sleep(0)

    print("Веду отсчёт. 3")

    await asyncio.sleep(0)

В этом коде есть два интересных слова: async и await.

async говорит Питону о том, что мы пишем не просто функцию, а асинхронную функцию. await прерывает исполнение функции, и возвращает управление программой наружу. После этого корутину можно запустить повторно, а затем еще и еще, и каждый раз она будет продолжать работу с того await, на котором прервалась ранее.

Например, в нашей функции count_to_three команда await встречается три раза, значит корутину можно вызвать четыре раза (да, не три!). Корутина будет работать до первого await, затем до второго, до третьего и на четвёртый раз выполнит остатки до конца.

Сразу покажем, как это выглядит на практике:

    coroutine_counter = count_to_three()

    print(coroutine_counter)  # <coroutine object count_to_three at 0x7f5a58486a98>

    coroutine_counter.send(None)  # Выведет "Веду отсчёт. 1"

    coroutine_counter.send(None)  # Выведет "Веду отсчёт. 2"

    coroutine_counter.send(None)  # Выведет "Веду отсчёт. 3"

Мы вызываем асинхронную функцию count_to_three, однако она не выводит на экран цифру 1, а возвращает корутину. Все асинхронные функции так делают. Это сделано для того, чтобы у вас был объект этой корутины в переменной. Теперь корутину можно запускать раз за разом, а она раз за разом будет делать кусочек и останавливаться на следующем await.

Чтобы запустить корутину, используют метод send(). При каждом запуске корутины этим методом она продолжает исполняться с последнего await, на котором она остановилась. Поэтому при новом запуске той же корутины срабатывает не тот же print, а следующий.

Нельзя просто .send(). Всегда нужно передавать какое-то значение. Воспринимайте .send(None) как команду «продолжи выполнять корутину».

Когда корутина закончится? Она остановится навсегда, когда закончатся все await или встретится return. Когда корутина заканчивается — она истощается и вызов .send() выдаёт ошибку:

    coroutine_counter = count_to_three()

    coroutine_counter.send(None)  # Выведет "Веду отсчёт. 1"

    coroutine_counter.send(None)  # Выведет "Веду отсчёт. 2"

    coroutine_counter.send(None)  # Выведет "Веду отсчёт. 3"

    coroutine_counter.send(None)  # Выбросит ошибку StopIteration

 

Вот еще пример асинхронного кода:

    import asyncio

    async def hello():

        await asyncio.sleep(1)

        print("Hello")

    async def world():

        await asyncio.sleep(2)

        print("World")

   

    async def main():

        await asyncio.gather(hello(), world())

    if __name__ == '__main__':

        asyncio.run(main())

В этом примере мы определяем 3 асинхронные функции: hello(), world() и main(). Функции hello() и world() печатают соответствующие сообщения и ждут 1 и 2 секунды
соответственно.

Функция main() запускает эти две функции одновременно с помощью asyncio.gather() и ждет, пока они завершат свою работу. Затем мы запускаем функцию main() с помощью asyncio.run(). В результате мы получим сообщения "Hello" и "World", каждое через 1 и 2 секунды соответственно, при этом результаты двух задач были получены почти одновременно.


Вам могут быть интересны материалы:

Плюсы онлайн-занятий. Кому подходит такой формат?

Онлайн-занятия имеют свои плюсы и недостатки. Рассмотрим некоторые преимущества онлайн-занятий по программированию.

Кто такой дизайнер и как им стать?

Меня часто спрашивают, кто такой дизайнер и как им стать? Давайте поговорим об этом и немного разберемся что же за профессия такая — дизайнер.

Библиотеки для разработки игр на Python

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


Наш сайт использует куки.
Пользуясь сайтом вы соглашаетесь
на обработку персональных данных.
Согласиться и закрыть это окно - нажмите «ОК».
OK