2011-03-12 13 views
18

Hasta donde sé, la principal diferencia entre las operaciones síncronas y asíncronas. Es decir. write() o read() frente a async_write() y async_read() es que los primeros, no regresan hasta que finalice la operación -o error-, y los últimos, vuelven inmediatamente.Se necesitan algunas aclaraciones sobre las operaciones asio síncronas y asíncronas

Debido a que las operaciones asincrónicas están controladas por un io_service.run() que no termina hasta que las operaciones controladas hayan finalizado. Me parece que en las operaciones secuenciales como los implicados en las conexiones TCP/IP con protocolos como POP3, en el que la operación es una secuencia tales como:

C: <connect> 
S: Ok. 
C: User... 
S: Ok. 
C: Password 
S: Ok. 
C: Command 
S: answer 
C: Command 
S: answer 
... 
C: bye 
S: <close> 

La diferencia entre los operadores síncrono/asíncrono no tiene mucho sentido.

Por supuesto, en ambas operaciones siempre existe el riesgo de que el flujo del programa se detenga indefinidamente por alguna circunstancia -en este caso el uso de temporizadores-, pero me gustaría conocer algunas opiniones más autorizadas en esta materia.

Debo admitir que la pregunta está bastante mal definida, pero me gustaría escuchar algunos consejos sobre cuándo usar una u otra. Me he encontrado con problemas al depurar con MS Visual Studio con respecto a las operaciones de SSL asíncronas en un cliente POP3 en el que ahora estoy trabajando, y algunas veces pienso que quizás sea una mala idea usar asincrono en esto.

+4

+1 Ni siquiera cerca de una pregunta mal definida. La programación asincrónica es difícil, no se avergüence de hacer preguntas al respecto. –

Respuesta

3

Supongo que la elección de síncrono/asíncrono es muy específico de la aplicación. Estoy de acuerdo en que el paradigma asíncrono puede hacer que el código y la depuración sean mucho más complejos, pero tiene sus ventajas.

Para ilustrar, la razón principal por la que cambiamos de IO sincrónico para impulsar asio con async IO es que en nuestra aplicación no era una opción bloquear IO, tenemos un servidor de transmisión multimedia en el que estaba transmitiendo paquetes de medios a múltiples clientes después de haber sido codificados. El problema era que los problemas de red daban como resultado que toda la interconexión de captura-codificación-entrega se bloquease efectivamente (por ejemplo, si la conexión a un solo cliente fallaba).

Para resumir, en mi (ltd) experiencia con IO asíncrono, puede ser útil en situaciones donde tiene que hacer otro trabajo mientras espera que IO lo complete (como servir a otros clientes, etc.) . En sistemas o escenarios, donde tiene que esperar que el resultado del IO continúe, sería mucho más simple usar IO sincrónico.

También tendría sentido en los sistemas de comunicación dúplex (por ejemplo, protocolos más complejos como SIP, RTSP donde tanto el cliente como el servidor pueden enviar solicitudes). Ha pasado un tiempo desde que he tratado con POP, pero para el intercambio simple en su ejemplo, async IO podría considerarse excesivo. Cambiaría a Async IO solo una vez que estaba seguro de que sincronizar IO no es suficiente para cumplir con mis requisitos.

WRT para impulsar la documentación asio, encontré que la mejor manera de familiarizarme con esto era trabajar con los ejemplos. Además, un enlace que quizás desee verificar es http://en.highscore.de/cpp/boost/index.html. Tiene un capítulo muy bueno sobre el aumento de asio. También Chris Kohlhoff's (author of asio) blog tiene algunos artículos realmente excelentes que vale la pena echarle un vistazo.

+0

Gracias por su contribución. Tus palabras tienen sentido para mí, y el libro de Higscore desconocido hasta ahora. –

31

El Boost.Asio documentation realmente hace un trabajo fantástico explicando los dos conceptos. Como Ralf mentioned, Chris también tiene un gran blog que describe conceptos asincrónicos. El ejemplo parking meter que explica cómo funcionan los tiempos de espera es particularmente interesante, como es el ejemplo bind illustrated.

En primer lugar, considerar una operación de conexión sincrónica:

synchronous connect

flujo El control es bastante sencillo aquí, su programa invoca alguna API (1) para conectar un enchufe. La API utiliza un servicio de E/S (2) para realizar la operación en el sistema operativo (3). Una vez que se completa esta operación (4 y 5), el control regresa a su programa inmediatamente después (6) con alguna indicación de éxito o falla.

la operación asincrónica análoga tiene un flujo de control completamente diferente:

asynchronous connect

Aquí, la aplicación se inicia la operación (1) utilizando el servicio mismo I/O (2), pero el flujo de control es invertido La finalización de la operación hace que el servicio de E/S notifique a su programa a través de un controlador de finalización. El tiempo entre el paso 3 y el momento en que se completó la operación se contuvo por completo dentro de la operación de conexión para el caso síncrono.

Puede ver que la carcasa sincrónica es naturalmente más fácil de entender para la mayoría de los programadores, ya que representa los paradigmas de flujo de control tradicionales. El flujo de control invertido utilizado por las operaciones asincrónicas es difícil de entender, a menudo obliga a su programa a dividir las operaciones en los métodos start y handle donde la lógica se desplaza. Sin embargo, una vez que tenga una comprensión básica de este flujo de control, se dará cuenta de lo poderoso que es realmente el concepto. Algunas de las ventajas de la programación asincrónica son:

  • Desacoplamientos enhebrados desde concurrencia. Realice una operación de larga ejecución; para el caso síncrono, a menudo crearía un hilo separado para manejar la operación y evitar que la GUI de la aplicación deje de responder. Este concepto funciona bien a pequeña escala, pero rápidamente se desmorona en un puñado de hilos.

  • Mayor rendimiento. El diseño de hilo por conexión simplemente no escala. Vea el C10K problem.

  • Composición (o encadenamiento). Las operaciones de nivel superior pueden estar compuestas de múltiples manejadores de finalización. Considere la posibilidad de transferir una imagen JPEG, el protocolo podría dictar que los primeros 40 bytes incluyan un encabezado que describa el tamaño de la imagen, la forma, tal vez alguna otra información. El primer controlador de finalización para enviar este encabezado puede iniciar la segunda operación para enviar los datos de imagen. La operación de nivel superior sendImage() no necesita conocer ni preocuparse por el método de encadenamiento utilizado para implementar la transferencia de datos.

  • Tiempos de espera y posibilidad de cancelación. Existen formas específicas de plataforma para agotar el tiempo de espera de una operación de larga ejecución (por ejemplo, SO_RCVTIMEO y SO_SNDTIMEO). El uso de operaciones asíncronas permite el uso de deadline_timer cancelando operaciones de larga ejecución en todas las plataformas compatibles.


Por supuesto, tanto en las operaciones no es Allways el riesgo de que el programa fluya paradas indefinidamente por alguna circunstancia -hay el uso de timers-, pero me gustaría conocer algunos más opiniones autorizadas en este asunto.

Mi experiencia personal con Asio se basa en la escalabilidad. El software de escritura para supercomputers requiere bastante cuidado cuando se trata de recursos limitados como memoria, hilos, tomas de corriente, etc. Usar un hilo por conexión para ~ 2 millones de operaciones simultáneas es un diseño que está muerto al llegar.

+2

A pesar del tiempo transcurrido usándolo, de vez en cuando, Internet todavía me da un toque de "magia". En este caso, la maravilla de tener como buenos maestros gratis. Gracias. –

+0

Siempre encuentro dificultades para entender la frase "flujo de control invertido". Entonces, ¿podría explicar la palabra "invertido" en este contexto? "Su aplicación inicia la operación (1) usando el mismo servicio de E/S (2), ** pero el flujo de control se invierte **." *? Aunque comprendo que el control fluye muy bien, y no puedo conectar el término "invertido" con lo que está sucediendo en el caso asíncrono. Para mí, parece que se elige una palabra aleatoria para dar * el flujo de control * un nombre o etiqueta. – Nawaz

+0

** flujo de control invertido ** significa que el marco o la biblioteca (Asio en esta respuesta) vuelve a llamar al programa, estas son las devoluciones de llamada cuando finaliza la operación asincrónica. Compare con la programación de procedimiento típica donde el programa llama al marco o biblioteca directamente, por ejemplo: una operación síncrona 'send()' devuelve el control cuando se completa. –

0

Una respuesta simple es: (cita de here con pocas modificaciones)

En clientes de sincronización Todo sucede en serie. Si envía un comando, se pondrá en cola detrás del anterior hasta que termine. Por lo general, una aplicación de subproceso único.

En ASync todo sucede simultáneamente. Usualmente aplicaciones de subprocesos múltiples que llevarán a cabo múltiples tareas al mismo tiempo.

+2

Javascript es de un solo subproceso y asincrónico ... y maravilloso. No creo que async esté conectado a multiproceso –

+0

Voto a la baja: no creo que esto sea correcto. Una forma de manejar conexiones de red múltiples es tener un subproceso o un proceso para cada conexión, y cada una de las conexiones ejecutándose en su propio subproceso/proceso, siendo todas las E/S síncronas. En el diseño de E/S asíncronas, puede tener cualquier cantidad de subprocesos o procesos, incluso uno solo, que manejen conexiones múltiples. De hecho, supongo que una de las principales motivaciones para inventar mecanismos de E/S asíncronas era deshacerse de la necesidad de escribir (excesivamente) código multiproceso que en algunas plataformas presentaba sus propios problemas de escalabilidad. – FooF

Cuestiones relacionadas