Cuando oímos hablar de Asincronía o Multihilo podemos caer en el error de confundir o de atribuir en alguno de los dos conceptos alguna relación entre ellos que lo único que hace es confundirnos. En este post mi intención es dar a conocer estos dos paradigmas, expondré algún ejemplo de ellos en tecnología .NET.
Entendiendo lo síncrono y lo asíncrono…
Para entrar a hablar de asincronía tendré que explicarlo através de su contrario , la sincronía.
Los procesos síncronos son todos aquellos que se ejecutan de principio a fin esperando la respuesta, mientras que los procesos asíncronos invocan la ejecución, pero no esperan respuesta que será gestionada por una callback.
Cuando hablamos de un proceso síncrono o asíncrono podemos poner como ejemplo la labor que desempeña un camarero de un restaurante. Un camarero síncrono atiende la petición del cliente y va al cocinero a pedirle el plato.Al ser síncrono se espera delante del cocinero a que acabe de cocinar el plato y al acabar se lo da al cliente mientras los demás clientes están esperando.
Cuando el camarero es asíncrono atiende a las peticiones de un cliente y le dice al cocinero lo que tiene que hacer y seguidamente atiende a la petición de otro cliente y así sucesivamente.
Multithreading (Multiproceso)
El paradigma del Multithreading nos permite dividir la carga de trabajo en diferentes unidades de ejecución (Hilos o Threats) para que se ejecuten simultáneamente, estos Hilos pueden tener sub-threads asociados. Este diseño de computación crea la estrategia “Divide and Conquer” (Dividir y conquistar) y se utiliza para minimizar los tiempos de ejecución de los procesos de una aplicación, sistema operativo etc…
Para poner un ejemplo mundano podríamos hacer un símil con un supermercado. En el supermercado se genera una cola para efectuar el cobro a sus clientes en caja y como la cantidad de clientes es tal que el tiempo para despacharlos a todos es algo largo, se habilita la otra caja para que parte de los clientes sean despachados junto con los de la otra cola simultáneamente repartiendo así la carga de trabajo.
Métodos Async en .Net
En .Net tenemos la posibilidad de liberar el Thread UI (generalmente es el principal) de la espera de estas respuestas. En el caso de una aplicación ASP.NET servirá para no bloquear los threads que se ejecutan en IIS y atienden peticiones entrantes. En aplicaciones web JavaScript, siendo un entorno de ejecución mono-thread, sirve para que la pantalla no quedase “congelada” y siga “escuchando” las peticiones del usuario. En definitiva el async en .Net es una “Inversion Of Control callback galore” que nos permitirá gestionar las callbacks de nuestras llamadas de forma asíncrona.
Para utilizar la asincronia con async/await se marcan los métodos con clausula async, que levanta una máquina de estados asociada al método que se está ejecutando. Por lo tanto en toda la aplicación habrá una sucesión de máquinas de estados, encargadas de controlar, valga la redundancia, el estado de la “computación” asociada. Hay que tener en cuenta que la propia clausula async va con su correspondiente clausula await delante del método que vamos a llamar asíncronamente.
Aquí exponemos un par de métodos Async que hacen las llamadas correspondientes a unos servicios, en ambos casos estamos “awaitando” la llamada a estos …
Ambos métodos aparecen en el siguiente gráfico con sus respectivas máquinas de estado.
La confusión de Async y Multithread
Un error general de concepto es pensar que cuando utilizamos async estamos haciendo multithread y eso no es cierto, al menos no siempre, ni tampoco directamente. Me explico:
Cuando llamamos a nuestros métodos precedidos de cláusula async lo que hacemos por detrás es levantar una máquina de estados para el procesamiento de la callback de forma asíncrona. Los métodos async en si no gestionan el multhreading, sinó que cuando hacemos un await ese retorna un Task (System.threading.Tasks) concepto muy parecido a las Promise javascript, que representa una computación.
El .Net tambien se sirve de la librería Task para crear hilos, pero la simple invocacion de un metodo awaitable no desencadena esta creacion de hilos. Por lo tanto, lo que es multithreading es lo que gestiona Task, Async se encarga de gestionar CallBackStacks.
Si nos fijamos, siempre que utilizamos métodos async en .Net utilizamos el tipo Task en la especificación del método, ya que las unidades de ejecución (hilos) los gestionará esa librería(System.threading.Tasks).Si de lo contrario no utilizaramos Task y utilizaramos un async de void crearíamos lo que se llama un “Fire and forget” (“Dispara y olvida”) que disparará la ejecución pero no gestionará ningún tipo de callback. Es una practica muy poco aconsejable, por no decir prohibida a no ser que queramos disparar algún proceso de escritura de traza o por el estilo…
Para finalizar mostraré el gráfico anterior extendido, para ver como se relacionan async I multithread.
Referencias:
- https://msdn.microsoft.com/es-es/library/system.threading.tasks.taskscheduler(v=vs.110).aspx
- http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx
- http://apmblog.dynatrace.com/2014/10/09/behind-net-4-5-async-scene-performance-impact-asynchronous-HYPERLINK «http://apmblog.dynatrace.com/2014/10/09/behind-net-4-5-async-scene-performance-impact-asynchronous-programming-c/»programming-c/
- https://msdn.microsoft.com/library/hh191443.aspx#BKMK_Threads
Agradecimientos a Roberto Grassi por la masterClass sobre asincronía y multithreading
Averigua cómo SOGETI puede ayudarte en la puesta en marcha de proyectos IT a través de soluciones Microsoft.
Eduard Moret es técnico superior en desarrollo de aplicaciones informáticas y actualmente especializado en tecnología .Net. Amante de la computación gráfica y la programación, Eduard se incorporó a Sogeti en 2015. Actualmente desempeña su labor en la empresa como programador Junior.
Muy buena explicación, muchas gracias
Me gustaMe gusta
Pingback: Asincronía en JavaScript | itblogsogeti