Асинхронный против многопоточности - есть ли разница?

133

Всегда ли асинхронный вызов создает новый поток? Какая разница между двумя?

Всегда ли асинхронный вызов создает или использует новый поток?

Википедия говорит :

В компьютерном программировании асинхронные события - это события, происходящие независимо от основного потока программы. Асинхронные действия - это действия, выполняемые по неблокирующей схеме, позволяющие основному потоку программы продолжить обработку.

Я знаю, что асинхронные вызовы могут выполняться в отдельных потоках? Как это возможно?

Тед смит
источник
1
В JavaScript нет потоков, но есть вызовы асинхронных методов.
Ajedi32
1
В любой системе, в которой один процесс управляет несколькими подпроцессами, процесс управления может обеспечивать асинхронную работу подпроцессов. В случае JavaScript браузер предоставляет вычислительный поток. Когда какая-либо функция выполняет асинхронный вызов, браузер может сохранить контекст для этой функции. Теперь тот же единственный поток браузера может изменить контекст, чтобы возобновить выполнение другой функции. В то время как в традиционных многопоточных программах один поток выполняет одни функциональные блоки, чтобы позволить другому потоку выполнять другую функцию. Каждый поток синхронно выполняет свою функцию.
Майк

Ответы:

82

Этот вопрос слишком общий, чтобы на него можно было ответить.

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

Асинхронный просто означает, что вызывающий поток не сидит и не ждет ответа, а также асинхронная активность не происходит в вызывающем потоке.

Помимо этого, вам нужно будет уточнить детали.

Майкл Кон
источник
7
Итак, в основном я прав, говоря: многопоточность == Использование нескольких потоков для обеспечения преимуществ обработки для задач, интенсивно использующих процессор, которые [в идеале] могут использовать преимущества нескольких процессоров, а также преимущества в асинхронных ситуациях. Асинхронность == процесс, который это делает, в то время как состояние, вызвавшее процесс, не должно ждать его завершения. (Для этого не обязательно использовать несколько потоков - т. Е. Ответственность могут нести другие компоненты оборудования).
Эван Севи
6
@Michael - Не могли бы вы объяснить на примере, как асинхронное программирование может происходить в одном потоке?
Кумар Вайбхав
7
@KumarVaibhav - наиболее распространенный пример - когда один поток работает с элементами из очереди (например, с очередью сообщений Windows). Если программа имеет обыкновение отправлять элементы в свою собственную очередь (общий шаблон), то бит кода, который отправляет элемент, не ждет завершения операции, а просто возвращается. Об этой операции в должное время позаботится основной цикл.
Майкл Кон
3
Может быть разница между тем, как написан код, и тем, как он выполняется. Например, в C # у меня может быть метод, запускающий асинхронную задачу, мой метод полностью поддерживает асинхронность и может делать другие вещи, не дожидаясь завершения задачи. Однако CLR может также решить встроить мою задачу и выполнить ее синхронно.
Майк,
какой поток выполняет ожидаемую задачу? метод, помеченный как a-sync, выполняется синхронно, пока не достигнет ключевого слова await, в этот момент какой поток выполняет эту ожидаемую задачу?
102

Всякий раз, когда операция, которая должна выполняться асинхронно, не требует, чтобы ЦП выполнял работу, эту операцию можно выполнить без создания другого потока. Например, если асинхронная операция - это ввод-вывод, ЦП не должен ждать завершения ввода-вывода. Ему просто нужно запустить операцию, а затем можно перейти к другой работе, пока оборудование ввода-вывода (контроллер диска, сетевой интерфейс и т. Д.) Выполняет операции ввода-вывода. Аппаратное обеспечение сообщает процессору о завершении, прерывая работу процессора, а затем операционная система передает событие вашему приложению.

Часто абстракции и API более высокого уровня не раскрывают базовые асинхронные API, доступные из ОС и базового оборудования. В таких случаях обычно проще создавать потоки для выполнения асинхронных операций, даже если порожденный поток просто ожидает операции ввода-вывода.

Если асинхронная операция требует, чтобы ЦП выполнял работу, то обычно эта операция должна выполняться в другом потоке, чтобы она была действительно асинхронной. Даже в этом случае он действительно будет асинхронным только при наличии более одной исполнительной единицы.

karunski
источник
1
Хорошо объяснено, спасибо; но у меня есть вопрос. Вы упомянули, что «Например, если асинхронная операция - это ввод-вывод, ЦП не должен ждать завершения ввода-вывода. Ему просто нужно начать операцию». Мой вопрос: когда программа является однопоточной и, скажем, в строке кода 3 вы вызываете операцию ввода-вывода, тогда как вы можете запустить операцию в строке 3 и выполнить строку 4, не дожидаясь завершения операции ввода-вывода ? Для меня я должен поместить код в строке 3 в новый поток, чтобы строка 4 выполнялась, не дожидаясь завершения операции ввода-вывода. [Перспектива Java pgm]
паук
1
причина в том, что, хотя ЦП не должен ждать, ЦП будет ждать завершения операции ввода-вывода ... Я считаю, что ваш второй абзац является ответом на мой запрос. В таком случае мне нужно сделать вывод, что в Java асинхронные вызовы должны выполняться в другом потоке. Пожалуйста, поправьте меня, если я ошибаюсь, или дайте мне знать, если мне нужно опубликовать новый SO qn
spiderman
@spiderman Некоторые языки, например Node.js, имеют модель асинхронного программирования. Язык и среда выполнения предоставляют встроенные средства, которые позволяют выполнять строку 4 в одном потоке даже до завершения операции ввода-вывода. Это достигается за счет того, что в строке 3 предоставляется обратный вызов, который среда выполнения будет вызывать после завершения ввода-вывода.
jrahhali
@spiderman может быть ... функция Async ОС просто возвращает false или что-то в этом роде.
Byeongin Yoon
18

Нет, асинхронные вызовы не всегда связаны с потоками.

Обычно они запускают какую-то операцию, которая продолжается параллельно с вызывающим. Но эта операция может выполняться другим процессом, ОС, другим оборудованием (например, контроллером диска), другим компьютером в сети или человеком. Потоки - не единственный способ делать вещи параллельно.

Джейсон Орендорфф
источник
12

JavaScript является однопоточным и асинхронным. Например, когда вы используете XmlHttpRequest, вы предоставляете ему функцию обратного вызова, которая будет выполняться асинхронно при возврате ответа.

У Джона Ресига есть хорошее объяснение связанной с этим проблемы работы таймеров в JavaScript .

Джордж В. Рейли
источник
12

Многопоточность означает, что в одном процессе выполняется более одной операции. В то время как асинхронное программирование распространяется по процессам. Например, если мои операции вызывают веб-службу, потоку не нужно ждать возврата веб-службы. Здесь мы используем асинхронное программирование, которое позволяет потоку не ждать завершения процесса на другой машине. И когда он начинает получать ответ от веб-службы, он может прервать основной поток, чтобы сказать, что веб-служба завершила обработку запроса. Теперь основной поток может обработать результат.

Муруган Гопалан
источник
Я бы немного не согласился. Я написал однопоточный HTTP-сервер, который обрабатывал несколько одновременных запросов с использованием асинхронного завершения ввода-вывода. Async не требует, чтобы что-то происходило в нескольких путях выполнения, это просто означает, что несколько вычислительных потоков могут перекрываться. Другой способ взглянуть на это состоит в том, что в однопоточной ОС я могу запустить 2 процесса «одновременно». С точки зрения каждого процесса, они работают синхронно. Однако с точки зрения ОС он работает асинхронно.
Майк
11

В Windows всегда использовалась асинхронная обработка с момента времени без прерывания (версии 2.13, 3.0, 3.1 и т.д.) с использованием цикла сообщений, задолго до поддержки реальных потоков. Итак, чтобы ответить на ваш вопрос, нет, нет необходимости создавать поток для выполнения асинхронной обработки.

Otávio Décio
источник
@dmckee - интересно, как разные системы развиваются одинаково.
Otávio Décio 01
8

Асинхронные вызовы даже не обязательно должны происходить в той же системе / устройстве, что и вызывающая вызов. Итак, если вопрос в том, требует ли асинхронный вызов потока в текущем процессе, ответ - нет. Однако где-то должен быть поток выполнения, обрабатывающий асинхронный запрос.

Поток исполнения - это расплывчатый термин. В системах кооперативного управления задачами, таких как ранние ОС Macintosh и Windows, поток выполнения мог быть просто тем же процессом, который выполнял запрос, выполняя другой стек, указатель инструкций и т. Д. Однако когда люди обычно говорят об асинхронных вызовах , они обычно означают вызовы, которые обрабатываются другим потоком, если он является внутрипроцессным (т. е. в рамках того же процесса), или другим процессом, если он является межпроцессным.

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

Майк
источник
7

Некоторые системы позволяют использовать преимущества параллелизма в ядре для некоторых средств с помощью обратных вызовов. Для довольно малоизвестного примера, асинхронные обратные вызовы ввода-вывода использовались для реализации неблокирующих интернет-серверов еще в дни без вытесняющей многозадачности Mac System 6-8.

Таким образом, у вас есть параллельные потоки выполнения «внутри» вашей программы без потоков как таковых .

dmckee --- котенок экс-модератора
источник
5

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

Есть примеры однопоточных асинхронных программ. Что-то вроде:

...do something
...send some async request
while (not done)
    ...do something else
    ...do async check for results
Милан Бабушков
источник
2

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

Иногда, в зависимости от ситуации, вы можете захотеть вызвать асинхронный метод, но сделать так, чтобы он казался пользователю синхронным (т. Е. Блокировать до тех пор, пока асинхронный метод не сообщит о завершении). Это может быть достигнуто с помощью Win32 API, таких как WaitForSingleObject .

LeopardSkinPillBoxHat
источник
Это верно для некоторых систем, но не для всех. Unix не требует, чтобы вы создавали или использовали другой поток, если только вы не называете ядро ​​другим потоком, что, как я полагаю, является одним из способов взглянуть на него.
Craig S
Это не так и в Windows. Например, перекрывающийся ввод-вывод является асинхронным.
Джейсон Орендорфф