@paulwer

Про асинхронность & многопоточность & мультипроцессинг в программировании?

Всем привет!
Знаю, что на эту тему уже очень много статей, но хотелось бы окончательно "расставить все по полочкам".
Хочу поговорить про асинхронность, мультипроцессинг и многопоточность.
Знаю о такой вещи, как конкурентность. Этот термин говорит о том, что за определенный период времени программа выполнит более одной задачи. Не важно как - они будут выполняться параллельно или одна задача будет приостанавливать другую. Теперь про параллельность. Она является "подмножеством" конкурентности (? это же так ?). Она говорит о том, что в реализации конкурентности одна задача НЕ будет приостанавливать другую. Они будут выполняться параллельно. Примерами параллельности являются мультипроцессинг и многопоточность. И еще асинхронность, как я понял. Первый вопрос мой состоит вот в чем: в асинхронном коде задачи как бы не выполняются абсолютно параллельно. Они выполняются по очереди, просто не приостанавливая главный поток, как в синхронном коде. А вот многопоточные и мультипроцессорные программы действительно выполняются параллельно (? или не совсем ?).
И еще один вопрос. Наверное, глупый. Например в нашей программе есть celery (первое, что пришло в голову). В нем выполняются определенные фоновые задачи. Насколько я знаю, celery мы даже запускаем в терминале отдельно. Получается, он выполняется другим потоком? Или я конкретно туплю? xd
  • Вопрос задан
  • 148 просмотров
Решения вопроса 2
sergey-gornostaev
@sergey-gornostaev Куратор тега Многопоточность
Седой и строгий
С терминологией в этой области у многих путаница. Ситуацию усложняет то, что одни и те же термины могут по-разному использоваться в разных контекстах и разных средах. Например самый общий термин "асинхронность" в общем смысле синоним многозадачности, то есть одновременного выполнения произвольного количества задач. Но часто под "асинхронностью" подразумевают мультиплексирование неблокирующихся сокетов в цикле событий. Конкурентность в контексте выполняемой работы - это одновременное выполнение разных задач. Параллельность в том же контексте - это одновременное выполнение одной задачи на разных данных. В контексте же того, как задачи выполняются, первое может означать, что асинхронность выполнения задач лимитировано конкурентным доступом к некому общему ресурсу, например процессору, а второе - возможность задач выполняться независимо друг от друга, например на разных ядрах. Запускать асинхронные задачи можно различными способами:
  1. В отдельных процессах, что обычно называют мультипроцессингом, и это как раз то, что делает Celery;
  2. В отдельных потоках, что называются многопоточностью;
  3. В сопрограммах или легковесных потоках, управляемых циклом событий, что часто называют асинхронностью, как я уже писал.
  4. На GPU;
  5. На разных машинах, что обычно происходит в распределённых системах.

Первый вопрос мой состоит вот в чем: в асинхронном коде задачи как бы не выполняются абсолютно параллельно. Они выполняются по очереди, просто не приостанавливая главный поток, как в синхронном коде. А вот многопоточные и мультипроцессорные программы действительно выполняются параллельно (? или не совсем ?).

С этим поможет разобраться, во-первых, понимание кооперативной и совместной или вытесняющей многозадачности, а во-вторых, понимание того, что многозадачность реализована на каждом уровне абстракции, от железа и ядра операционной системы до прикладного кода. В модели кооперативной многозадачности задачи самостоятельно отдают друг другу управление, когда достигают некоторой точки, в которой продолжить работу не могут. Например, при ожидании поступления данных из сети. В вытесняющей многозадачности есть некий планировщик, который решает какую из задач остановить, а какую запустить и старается распределить процессор между задачами примерно поровну. То, что называют асинхронным кодом, обычно использует кооперативную многозадачность. Если грубо, где-то в глубине среды исполнения крутится бесконечный цикл, на каждой итерации которого запускается одна из сопрограмм, работает пока не решит отпустить управление, после чего происходит следующая итерация и запуск следующей сопрограммы. Тонкость в том, что например питонячий цикл событий крутится внутри потока, который выполняется внутри процесса интерпретатора, который вместе с другими процессами в системе делит процессор под управлением системного планировщика. Так что некая асинхронная функция в вашем коде выполняется одновременно и кооперативно, и совместно. Её так же, как и любой поток в любом процессе может остановить системный планировщик, чтобы отдать процессор другой задаче. Абсолютной параллельности добиться в принципе невозможно, даже если у вас будет тысяча ядер, всё равно выполняемые на них задачи будут останавливаться, как минимум механизмом когерентности кэшей.
Ответ написан
Комментировать
IvanU7n
@IvanU7n
nothing interesting here
без понятия что такое celery, но оно вроде как и не сильно релевантно
про мультпроцессинг и многопоточность всё вроде правильно

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

например в JavaScript с его event-loop задачи (считай события, что есть работа) становятся в "очередь" и ждут там своего часа, однако если какая-та задача сильно задумалась, все остальные задачи ничего с этим сделать не могут, т.е. это однопоточная асинхронная обработка (всяких Worker-ов оставим за скобками)

если смотреть на nginx, то там примерно так же, за исключением что дочерних процессов, делающих основную работу, он запускает по количеству ядер, но один процесс внутри себя имеет такой же event-loop со всеми вытекающими последствиями

всё остальное ИМХО графоманство
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы