Один поток и асинхронная путаница

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

Я понял, что thread — это количество рабочих, а sync/async — это порядок задач. Я хотел бы спросить, верно ли мое понимание, на следующем примере.

Приходится делать бутерброд.

  1. Печь хлеб.
  2. Поджарьте яйца.
  3. Объединить.

Нить == сковородка.

  • Однопоточность и синхронизация:
    1. Положите хлеб на сковороду.
    2. просто наблюдайте, пока хлеб не испекся.
    3. Когда хлеб испекся, выньте хлеб из формы и положите на нее яйца.
  • Многопоточность и асинхронность:
    1. Несколько сковородок.
    2. Положите хлеб и яйца на разные противни соответственно.
    3. Неважно, что вы поставили первым, выньте завершенное.
  • Однопоточный и асинхронный:
    1. Одна кастрюля.
    2. Положите хлеб на противень.
    3. Хлеб был не весь испечен, но отложил его на некоторое время и положил яйца на эту сковороду.
    4. Яйца не все жареные, но я просто уберу их и положу хлеб на сковороду.
    5. Повторить...
  • Многопоточность и синхронизация:
    1. Есть несколько сковородок, но сначала мы будем печь хлеб на сковороде 1.
    2. Когда хлеб на сковороде 1 будет готов, поджарьте яйца на сковороде 2.

Правильно ли я понимаю?

+) Если да, то случай однопоточный/асинхронный как javascript, задача в цикле событий просто ждет в очереди и не прогрессирует, верно?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
27
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Пример отличный и смешной. Не забудьте взять позже другой для «Многопоточности и асинхронности», иначе он будет сожжен;) . В остальном мне кажется, что это правильно.

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

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

Асинхронную операцию можно разделить на несколько частей:

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

Часть 2 зависит от языка/фреймворка. Более того, что касается языка/фреймворка, иногда есть часть, состоящая в ожидании завершения задачи (операция блокировки). Это можно сделать, зациклив часть 2, пока состояние не будет завершено, но иногда это можно сделать немного эффективнее.

Спасибо за ответ. Но, кажется, я чего-то не понимаю. 1.the switch between bread and egg is not async, значит ли это, что заказ не гарантируется как b - e - b - e ? 2. Могу ли я понять, что the problem in your example означает, что мой пример не делает предположений о задачах, не связанных с процессором (pan)?

mishy 09.05.2022 06:36

не по теме) Возможно, мне не хватает понимания операций ввода-вывода. Разве процесс не использует ЦП в операции блокировки ввода-вывода? Даже если он неблокирующий, некоторое время не использует процессор в режиме ядра?

mishy 09.05.2022 06:37

1. Да заказ не гарантируется. Однако это очень зависит от целевой платформы/асинхронного метода. Но, как правило, асинхронная задача будет продолжаться до тех пор, пока ей не придется ждать какой-либо работы или пока работа не будет завершена. В этом случае сама задача совместно временно останавливает себя и позволяет другим выполняться. Это очень отличается от многопоточности, когда ОС регулярно переключается между двумя потоками, когда они конкурируют за одни и те же ядра (вытеснение). Медленный асинхронный процесс, который не очень сотрудничает, может помешать выполнению других в течение длительного времени. Возможная казнь b - b - e - e.

Jérôme Richard 09.05.2022 22:03

2. Я не уверен, что понял вашу мысль. Я бы сказал, что ваш пример не выполняет задачи рассмотреть возможность, кроме задач с интенсивным использованием ЦП (т.е. пан-жадных). Это более ясно?

Jérôme Richard 09.05.2022 22:07

Операции ввода-вывода немного сложны, и со временем все изменилось. Метод работы с асинхронными операциями ввода-вывода зависит от приложения, ОС и реальных API. Блокирование операций ввода-вывода стало стандартом последнего десятилетия, но это не лучшее решение. Когда приложение использует блокирующие операции, например, для чтения файла, оно делает запрос к ОС, которая добавляет его в очередь, которая может быть вычислена другим потоком позже или напрямую. Если ОС не может напрямую предоставить результат, запрашивающий поток прерывается ОС и помещается в список ожидания.

Jérôme Richard 09.05.2022 22:14

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

Jérôme Richard 09.05.2022 22:21

Некоторые высокоуровневые асинхронные API используют внутреннюю блокировку вызовов и не очень полезны. Некоторые другие используют неблокирующие вызовы и имеют основной четный поток, перебирающий все ожидающие запросы, чтобы проверить их завершение. Ни один из двух подходов не эффективен, хотя второй лучше, так как задачи не ждут. Основная ОС предоставляет для этого асинхронные API, но на практике они не всегда быстрее, чем использование предыдущих методов. Совсем недавно Linux предоставил новый быстрый способ сделать это эффективно (см. IO-Uring и Async-IO).

Jérôme Richard 09.05.2022 22:31

Другие вопросы по теме

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

Исполнителю пула потоков требуется предложение по функции вызова или несколько шагов перед вызовом executor.submit
Std элемент доступа к карте при создании новой безопасности одного потока
Ошибка Отсутствует указание типа. Предполагается . Примечание C++ не поддерживает инициализацию по умолчанию
Почему порождение процесса заставляет вычисления выполняться в два раза быстрее?
При этом синхронизация не работает. Почему? Я синхронизировал все методы. Может ли кто-нибудь рассказать и предоставить решение для того же?
Почему мои темы не работают так, как я ожидаю?
Я не понимаю эту пожизненную ошибку: создание потоков внутри функции структуры
Как заставить графический интерфейс Python Tkinter проверять, завершил ли другой поток внесение изменений в графический интерфейс?
Сколько потоков использует пользовательский код приложения Flutter?
Когда очередь приоритетов std сравнивает значения?