В чем разница между: асинхронными, неблокирующими, основанными на событиях архитектурами?

  1. в чем разница между:

    • асинхронные,
    • Неблокирующий и
    • Event-base архитектуры?
  2. может быть что-то асинхронные и неблокирующийсобытие на основе)?

  3. что самое важное в программировании, чтобы что-то иметь: асинхронный, неблокирующая и / или событийная база (или все 3)?

Если бы вы могли привести примеры, это было бы здорово.

этот вопрос задается, потому что я читал этот великий StackOverflow статья на аналогичную тему, но она не отвечает на мои вопросы выше.

5 ответов


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

Неблокирующий Этот термин в основном используется с IO. Это значит, что когда вы делаете системный вызов, он немедленно возвращается с любым результатом, который он имеет, не помещая ваш поток в спящий режим (с высокой вероятностью). Например, неблокирующие вызовы чтения/записи возвращаются с тем, что они могут сделать, и ожидают, что вызывающий вызов снова выполнит вызов. например, try_lock-это неблокирующий вызов. Он будет запираться только в том случае, если замок может быть приобретен. Обычная семантика для системных вызовов-блокировка. read будет ждать, пока у него не появятся данные, и переводить вызывающий поток в спящий режим.

событие-базы Этот термин происходит от libevent. неблокирующее чтение/запись звонков сами по себе бесполезны, потому что они не говорят вам, когда вы должны перезвонить (повтор). select/epoll / IOCompletionPort и т. д.-Это разные механизмы для выяснения из ОС "когда" ожидается, что эти вызовы вернут "интересные" данные. libevent и другие подобные библиотеки предоставляют оболочки для этих средств мониторинга событий, предоставляемых различными ОС, и предоставляют согласованный API для работы с которой работает через операционные системы. Неблокирующий IO идет рука об руку с Event-base.

Я думаю, что эти термины пересекаются. Например, протокол HTTP является синхронным, но реализация HTTP с использованием неблокирующего ввода-вывода может быть асинхронной. Опять же, неблокирующий вызов API, такой как read/write/try_lock, является синхронным (он сразу дает ответ), но "обработка данных" является асинхронной.


в асинхронном оборудовании код просит некоторую сущность что-то сделать и может делать другие вещи, пока действие выполняется; как только действие завершено, сущность обычно сигнализирует код каким-то образом. Неблокирующая архитектура будет отмечать спонтанно возникающие действия, которые могут быть интересны коду, и позволит коду спросить, какие такие действия произошли, но код будет знать о таких действиях только тогда, когда он явно спрашивает о них. Событие на основе архитектура утвердительно сообщить код, когда события происходят спонтанно.

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

в архитектуре блокирующего чтения код будет ждать, пока не прибудет 1000 байт или он не решит сдаться.

в архитектуре асинхронного чтения код сообщит драйверу, что он хочет 1,000 байт, и будет уведомлен, когда 1,000 байт прибыли.

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

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


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

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

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

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

эти три термина связаны, но для меня это разные понятия. Может быть, люди используют их несколько взаимозаменяемым образом.


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

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

Как правило, асинхронная архитектура-это архитектура на основе событий, не блокирующая.

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

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

Я удалил вышеуказанный абзац, потому что он не совсем корректен, как указано. Моим намерением было сказать это, хотя операции в системе неблокируются, например, вызовы на объект ОС и продолжение выполнения, характер однопоточного выполнения означает, что при запуске событий они будут конкурировать с другими задачами обработки за вычислительное время в потоке.


Так что ответ на ваш первый и второй вопрос:

non-blocking фактически то же самое, что и асинхронный - вы делаете вызов, и вы получите результат позже, но пока это происходит, вы можете сделать что-то еще. Блокировка наоборот. Вы ждете звонка, чтобы вернуться, прежде чем продолжить свое путешествие.

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

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

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

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

Если вы пишете серверный веб-сервер, то действуйте с осторожностью. Помните, что вы можете масштабировать по горизонтали намного дешевле. Netflix / Amazon / Google / Facebook являются очевидными исключениями из этого правила, хотя, чисто потому, что это работает дешевле для них использовать меньше оборудования.

Я скажу вам, почему асинхронный / неблокирующий код-это кошмар с серверными системами....

1) это становится отказом в обслуживании по производительности... нужно думать гораздо больше, и вы делаете много ошибок на этом пути.

2) трассировки стека в реактивном коде становятся неразборчивыми - трудно понять, что называется, что, когда, почему и как. Удачи с отладкой.

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

4) это сложнее проверить.

5) его сложнее поддерживать.

6) это больно. Программирование должно быть радостью и удовольствием. Только мазохисты любят боль. Люди, которые пишут параллельные/реактивные фреймворки, - садисты.

и да, я написал как sync, так и async. Я предпочитаю синхронный как 99.99 back-end приложения могут справиться с этой парадигмой. Интерфейсные приложения нуждаются в реактивном коде, без вопросов, и это всегда было так.

  1. Да, код может быть асинхронным, неблокирующим и основанным на событиях.

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