¿Cuál es la diferencia entre: arquitecturas asincrónicas, sin bloqueo y basadas en eventos?


84
  1. Cuál es la diferencia entre:

    • Asincrónico ,
    • No bloqueante y
    • ¿Arquitecturas basadas en eventos ?
  2. ¿Algo puede ser asincrónico y no bloqueante (y basado en eventos )?

  3. ¿Qué es más importante en la programación, tener algo: asincrónico, sin bloqueo y / o base de eventos (o los 3)?

Si pudiera proporcionar ejemplos, sería genial.

Se hace esta pregunta porque estaba leyendo este excelente artículo de StackOverflow sobre un tema similar, pero no responde a mis preguntas anteriores.

Respuestas:


91

Asincrónico Asincrónico significa literalmente no sincrónico. El correo electrónico es asincrónico. Envías un correo electrónico, no esperas recibir una respuesta AHORA. Pero no es sin bloqueo. Básicamente, lo que significa es una arquitectura en la que los "componentes" se envían mensajes entre sí sin esperar una respuesta inmediata. Las solicitudes HTTP son sincrónicas. Envíe una solicitud y obtenga una respuesta.

Sin bloqueo Este término se usa principalmente con IO. Lo que esto significa es que cuando realiza una llamada al sistema, regresará inmediatamente con cualquier resultado que tenga sin poner su hilo en suspensión (con alta probabilidad). Por ejemplo, las llamadas de lectura / escritura sin bloqueo regresan con todo lo que pueden hacer y esperan que la persona que llama ejecute la llamada nuevamente. try_lock, por ejemplo, es una llamada sin bloqueo. Se bloqueará solo si se puede adquirir el bloqueo. La semántica habitual para las llamadas a sistemas está bloqueando. read esperará hasta que tenga algunos datos y pondrá el hilo de llamada en suspensión.

Base de eventos Este término proviene de libevent. Las llamadas de lectura / escritura sin bloqueo en sí mismas son inútiles porque no le dicen "cuándo" debe devolverlas (reintentar). select / epoll / IOCompletionPort, etc. son mecanismos diferentes para averiguar desde el sistema operativo "cuándo" se espera que estas llamadas devuelvan datos "interesantes". libevent y otras bibliotecas similares proporcionan envoltorios sobre estas funciones de monitoreo de eventos proporcionadas por varios sistemas operativos y brindan una API consistente con la que trabajar y que se ejecuta en todos los sistemas operativos. IO sin bloqueo va de la mano con Event-base.

Creo que estos términos se superponen. Por ejemplo, el protocolo HTTP es síncrono, pero la implementación de HTTP que utiliza E / S sin bloqueo puede ser asíncrona. Una vez más, una llamada a la API sin bloqueo como read / write / try_lock es sincrónica (da una respuesta inmediatamente) pero el "manejo de datos" es asincrónico.


2
Un buen punto sobre el no bloqueo que requiere sondeo constante, mientras que el async puede basarse en push.
Alexander Torstling

Definió sincrónico como recibir una respuesta inmediata, pero cuando busco sincrónico en Google, todos los diccionarios lo definen como "sucediendo al mismo tiempo", no como "respuesta inmediata".
IntelliData

4
¿Cómo me bloquean cuando envío un correo electrónico pero no espero una respuesta? Puedo ocuparme de mis propios asuntos mientras espero una respuesta.
Koray Tugay

20

En un hardware asincrónico, el código le pide a alguna entidad que haga algo y es libre de hacer otras cosas mientras se realiza la acción; una vez que se completa la acción, la entidad normalmente señalará el código de alguna manera. Una arquitectura sin bloqueo tomará nota de las acciones que ocurren espontáneamente en las que el código podría estar interesado y permitirá que el código pregunte qué acciones han ocurrido, pero el código solo se dará cuenta de tales acciones cuando pregunte explícitamente sobre ellas. Una arquitectura basada en eventos notificará afirmativamente al código cuando los eventos ocurran espontáneamente.

Considere un puerto serie, desde el cual el código querrá recibir 1,000 bytes.

En una arquitectura de lectura de bloqueo, el código esperará hasta que hayan llegado 1000 bytes o decida darse por vencido.

En una arquitectura de lectura asincrónica, el código le dirá al controlador que quiere 1,000 bytes y se le notificará cuando hayan llegado 1,000 bytes.

En una arquitectura sin bloqueo, el código puede preguntar en cualquier momento cuántos bytes han llegado y puede leer cualquiera o todos esos datos cuando lo considere oportuno, pero la única forma de saber cuándo han llegado todos los datos es preguntar; si el código quiere averiguar en un cuarto de segundo cuándo ha llegado el byte 1000, debe verificar cada cuarto de segundo aproximadamente.

En una arquitectura basada en eventos, el controlador del puerto serie notificará a la aplicación cada vez que lleguen datos. El controlador no sabrá cuántos bytes quiere la aplicación, por lo que la aplicación debe poder manejar notificaciones de cantidades menores o mayores de lo que quiere la aplicación.


5

Entonces, para responder a su primera y segunda pregunta:

Sin bloqueo es efectivamente lo mismo que asincrónico: haces la llamada y obtendrás un resultado más tarde, pero mientras eso sucede, puedes hacer otra cosa. El bloqueo es lo contrario. Espera a que vuelva la llamada antes de continuar su viaje.

Ahora el código asincrónico / sin bloqueo suena absolutamente fantástico, y lo es. Pero tengo palabras de advertencia. Async / Non-block son excelentes cuando se trabaja en entornos restringidos, como en un teléfono móvil ... considere CPU / memoria limitada. También es bueno para el desarrollo de front-end, donde su código necesita reaccionar a un widget de UI de alguna manera.

La asincronía es fundamental para la forma en que todos los sistemas operativos deben funcionar: hacen las cosas por ti en segundo plano y activan tu código cuando han hecho lo que pediste, y cuando esa llamada falla, te dicen que no. funcionan mediante una excepción o algún tipo de código de retorno / objeto de error.

En el momento en que su código solicita algo que tardará un tiempo en responder, su sistema operativo sabe que puede estar ocupado haciendo otras cosas. Su código: un proceso, subproceso o equivalente, bloques. Su código es totalmente ajeno a lo que está sucediendo en el sistema operativo mientras espera que se establezca la conexión de red, o mientras espera esa respuesta de una solicitud HTTP, o mientras espera esa lectura / escritura de un archivo, y pronto. Su código podría "simplemente" estar esperando un clic del mouse. Lo que realmente estaba sucediendo durante ese tiempo era que su sistema operativo administraba, programaba y reaccionaba sin problemas a los "eventos": cosas que el sistema operativo busca, como administrar la memoria, E / S (teclado, mouse, disco, Internet), otras tareas, recuperación de fallos, etc.

Los sistemas operativos son jodidamente duros. Son realmente buenos para ocultarle a usted, el programador, todas las cosas complicadas de async / non-block. Y así es como la mayoría de los programadores llegaron a donde estamos hoy con el software. Ahora que estamos alcanzando los límites de la CPU, la gente dice que se pueden hacer cosas en paralelo para mejorar el rendimiento. Esto significa que Async / non-block parece algo muy favorable, y sí, si su software lo exige, puedo estar de acuerdo.

Si está escribiendo un servidor web back-end, proceda con precaución. Recuerde que puede escalar horizontalmente por mucho más barato. Sin embargo, Netflix / Amazon / Google / Facebook son excepciones obvias a esta regla, simplemente porque les resulta más barato usar menos hardware.

Te diré por qué el código asíncrono / sin bloqueo es una pesadilla con los sistemas de back-end ...

1) Se convierte en una negación de servicio en productividad ... tienes que pensar MUCHO más, y cometes muchos errores en el camino.

2) Los rastros de pila en el código reactivo se vuelven indescifrables: es difícil saber qué se llama qué, cuándo, por qué y cómo. Buena suerte con la depuración.

3) Tienes que pensar más en cómo fallan las cosas, especialmente cuando muchas cosas vuelven a estar fuera de orden de cómo las enviaste. En el viejo mundo, hacías una cosa a la vez.

4) Es más difícil de probar.

5) Es más difícil de mantener.

6) Es doloroso. La programación debe ser divertida y divertida. Solo a los masoquistas les gusta el dolor. Las personas que escriben marcos concurrentes / reactivos son sádicos.

Y sí, he escrito tanto sync como async. Prefiero la sincronización, ya que 99,99 de las aplicaciones de back-end pueden funcionar con este paradigma. Las aplicaciones de front-end necesitan código reactivo, sin lugar a dudas, y siempre ha sido así.

  1. Sí, el código puede ser asíncrono, sin bloqueo Y basado en eventos.

  2. Lo más importante en la programación es asegurarse de que su código funcione y responda en un período de tiempo aceptable. Cíñete a ese principio clave y no te equivocarás.


** ACTUALIZACIÓN ** Después de jugar con Go, y entender los canales y rutinas de go, debo decir que en realidad me gusta hacer que mi código sea más concurrente, porque las construcciones del lenguaje toman todo el dolor de los escritores de frameworks sádicos. Tenemos una "palabra segura" en el mundo del procesamiento asíncrono, y esa es "¡Adelante!"
user924272

4

Para mí, no bloqueo significa que la ejecución de una acción en un hilo no depende de la ejecución de otros hilos, en particular, no requiere una sección crítica.

Asincrónico significa que la ejecución ocurre fuera del flujo de la persona que llama y potencialmente se difiere. La ejecución suele ocurrir en otro hilo.

La lectura de datos simultáneos no se bloquea (no es necesario bloquear), pero es sincrónica. A la inversa, escribir datos al mismo tiempo de manera síncrona está bloqueando (requiere un bloqueo exclusivo). Una forma de hacerlo sin bloqueo desde la perspectiva del flujo principal es hacer que las escrituras sean asincrónicas y diferir su ejecución.

El concepto de evento es otra cosa, lo que en términos generales significa que se le informa cuando ocurre algo. Si las escrituras se han ejecutado de forma asincrónica, se puede generar un evento para informar a otras partes del sistema una vez que se ha ejecutado la escritura. Las otras partes responderán al evento. El sistema puede construirse únicamente sobre eventos como la única forma de comunicarse entre componentes (piense en el modelo de actor), pero no debe ser necesariamente el caso.

Los tres términos están relacionados, pero son conceptos diferentes para mí. Sin embargo, puede ser que la gente los use de una manera algo intercambiable.


2

Generalmente, una arquitectura sin bloqueo se basa en llamadas a métodos que, si bien pueden ejecutarse durante mucho tiempo en el hilo de trabajo , no bloquean el hilo de llamada . Si el hilo de llamada necesita adquirir información sobre o de la tarea que está ejecutando el hilo de trabajo, depende del hilo de llamada hacer eso.

Una arquitectura basada en eventos se basa en el concepto de código que se ejecuta en respuesta a eventos que se disparan. El tiempo de ejecución del código generalmente no es determinista, pero los eventos pueden invocar métodos de bloqueo; el hecho de que un sistema esté basado en eventos no significa que todo lo que hace no esté bloqueando.

Generalmente, una arquitectura asíncrona es una arquitectura sin bloqueo basada en eventos.

Cuando se realiza una llamada asíncrona, los controladores de eventos se registran con la API que proporciona servicios de sincronización, para notificar a la persona que llama que ha sucedido algo en lo que está interesado. La llamada regresa inmediatamente (comportamiento sin bloqueo) y la persona que llama es libre de continuar con la ejecución. Cuando los eventos se devuelven al proceso de llamada, se manejarán en algún hilo de ese proceso.

Es importante comprender si los eventos se manejarán en el mismo hilo o no, ya que esto afectará la naturaleza no bloqueante de la ejecución, pero no conozco personalmente ninguna biblioteca que realice una gestión de ejecución asíncrona en un solo hilo.

Eliminé el párrafo anterior porque no es estrictamente correcto como se indica. Mi intención era decir que aunque las operaciones en el sistema no son bloqueantes, como hacer llamadas a una instalación del sistema operativo y continuar con la ejecución, la naturaleza de la ejecución de un solo subproceso significa que cuando se disparan eventos, competirán con otras tareas de procesamiento para calcular el tiempo en el hilo.


¿No contradice su último párrafo su afirmación de que "la arquitectura asincrónica es ... no bloqueante"
nickb

Supongo que no hice un buen trabajo al abordar la parte de "definiciones" de su pregunta; Publicaré una actualización. Pero no, la naturaleza de la ejecución de un solo subproceso es que cada operación se bloquea intrínsecamente mientras se ejecuta , lo que hace que la asincronía sea aún más útil.
arootbeer
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.