Я читал различные статьи и подобные вопросы, и я знаю, что эти две концепции разные, но, похоже, я не знаю правильного ответа.
Я понял, что thread
— это количество рабочих, а sync/async
— это порядок задач.
Я хотел бы спросить, верно ли мое понимание, на следующем примере.
Приходится делать бутерброд.
Нить == сковородка.
Правильно ли я понимаю?
+) Если да, то случай однопоточный/асинхронный как javascript, задача в цикле событий просто ждет в очереди и не прогрессирует, верно?
Пример отличный и смешной. Не забудьте взять позже другой для «Многопоточности и асинхронности», иначе он будет сожжен;) . В остальном мне кажется, что это правильно.
Однако пример не очень хорош для случая «Однопоточный и асинхронный» и может быть источником путаницы. На практике упреждение (переключение между яйцами и хлебом) не гарантируется в асинхронном режиме. Как правило, это делается совместно. Проблема в том, что в вашем примере хлеб нельзя приготовить, пока есть яйца, так как есть только 1 кастрюля. На практике такая задача, как операции ввода-вывода, может выполняться без использования какого-либо ядра (т. е. панорамирования).
Асинхронность в основном полезна, чтобы не ждать завершения задачи, пока можно сделать что-то еще. Это не очень полезно для вычислительных задач. Например, если вы готовите 2 бутерброда для 2 друзей и не знаете, любят ли они яйца или бекон, вам нужно спросить их. Эта задача может быть асинхронной: вы можете задать первое, затем второе, затем приготовить хлеб на 1 или 2 сковороде, затем проверить ответы перед приготовлением яиц/маяка. Без асинхронности вам придется ждать ответа (возможно, в потоке), прежде чем готовить хлеб (что неэффективно).
Асинхронную операцию можно разделить на несколько частей:
Часть 2 зависит от языка/фреймворка. Более того, что касается языка/фреймворка, иногда есть часть, состоящая в ожидании завершения задачи (операция блокировки). Это можно сделать, зациклив часть 2, пока состояние не будет завершено, но иногда это можно сделать немного эффективнее.
не по теме) Возможно, мне не хватает понимания операций ввода-вывода. Разве процесс не использует ЦП в операции блокировки ввода-вывода? Даже если он неблокирующий, некоторое время не использует процессор в режиме ядра?
1. Да заказ не гарантируется. Однако это очень зависит от целевой платформы/асинхронного метода. Но, как правило, асинхронная задача будет продолжаться до тех пор, пока ей не придется ждать какой-либо работы или пока работа не будет завершена. В этом случае сама задача совместно временно останавливает себя и позволяет другим выполняться. Это очень отличается от многопоточности, когда ОС регулярно переключается между двумя потоками, когда они конкурируют за одни и те же ядра (вытеснение). Медленный асинхронный процесс, который не очень сотрудничает, может помешать выполнению других в течение длительного времени. Возможная казнь b - b - e - e
.
2. Я не уверен, что понял вашу мысль. Я бы сказал, что ваш пример не выполняет задачи рассмотреть возможность, кроме задач с интенсивным использованием ЦП (т.е. пан-жадных). Это более ясно?
Операции ввода-вывода немного сложны, и со временем все изменилось. Метод работы с асинхронными операциями ввода-вывода зависит от приложения, ОС и реальных API. Блокирование операций ввода-вывода стало стандартом последнего десятилетия, но это не лучшее решение. Когда приложение использует блокирующие операции, например, для чтения файла, оно делает запрос к ОС, которая добавляет его в очередь, которая может быть вычислена другим потоком позже или напрямую. Если ОС не может напрямую предоставить результат, запрашивающий поток прерывается ОС и помещается в список ожидания.
Когда операция завершена, ОС пробуждает поток, связанный с запросом, и блокирующий вызов возвращается. Как правило, ОС не зацикливается на событиях. Он отправляет запросы на устройства, и они используют аппаратные прерывания, чтобы вызвать выполнение функций ядра, которые решат заполнить некоторые очереди, прервать некоторые потоки и разбудить некоторые другие. Потоки ядра могут активно извлекать место в памяти, хотя они часто ждут, чтобы не потреблять ресурсы (и позволить пользовательскому потоку выполняться).
Некоторые высокоуровневые асинхронные API используют внутреннюю блокировку вызовов и не очень полезны. Некоторые другие используют неблокирующие вызовы и имеют основной четный поток, перебирающий все ожидающие запросы, чтобы проверить их завершение. Ни один из двух подходов не эффективен, хотя второй лучше, так как задачи не ждут. Основная ОС предоставляет для этого асинхронные API, но на практике они не всегда быстрее, чем использование предыдущих методов. Совсем недавно Linux предоставил новый быстрый способ сделать это эффективно (см. IO-Uring и Async-IO).
Спасибо за ответ. Но, кажется, я чего-то не понимаю. 1.
the switch between bread and egg is not async
, значит ли это, что заказ не гарантируется какb - e - b - e
? 2. Могу ли я понять, чтоthe problem in your example
означает, что мой пример не делает предположений о задачах, не связанных с процессором (pan)?