Kotlin Coroutines: Coroutines no son subprocesos ligeros. | Por Abhishek Kumar | enero de 2022



Ya que está aquí, asumo que está familiarizado con los conceptos de programación asincrónica y alguna forma de subprocesamiento múltiple. Si no es así, probablemente esté navegando borracho. dormir.
«Las corrutinas son subprocesos ligeros»: ¿cuántas veces te has encontrado con esta frase? Esta definición es simplemente absurda y no podría estar más lejos de su verdadero significado.
Hay confusión debido a declaraciones aparentemente inocentes en la documentación:
Las rutinas pueden considerarse subprocesos livianos, pero hay una serie de diferencias importantes que hacen que su uso en la vida real sea muy diferente al de los subprocesos.
dice»puedes ser tuHt Hilo ligero«, no es»es un hilo ligero«. Veo que la gente se confunde con las corrutinas solo porque siempre piensan en las corrutinas como hilos. Resolvamos esto entendiendo las diferencias principales.
¿Cuál es la forma más básica de enhebrar? Es el flujo de control secuencial en un programa. La palabra «secuencia» es importante aquí. Echa un vistazo a estas características:
fun firstFunction() {
//Code snippet 1
secondFunction()
//Code snippet 2
}fun secondFunction() {
//Code snippet 3
}
Si un hilo llama firstFunction
Entonces el código se ejecutará en el siguiente orden:
- Fragmento de código 1
- Fragmento de código 3
- Fragmento de código 2
Estos 3 fragmentos de código siempre se ejecutarán en el subproceso de llamada firstFunction
Y el orden de ejecución de estos tres fragmentos de código en un hilo siempre será el mismo.Otra forma de ver esto es Si la ejecución de una función comienza en un subproceso, el subproceso no estará inactivo hasta que la función regrese.
Esto puede ser un desperdicio. Especialmente cuando estamos hablando del hilo principal. ¿Qué pasa si los fragmentos 1 y 2 son tareas sencillas de «hacer rápido», pero el fragmento 3 implica operaciones de E/S que consumen recursos? Si los fragmentos 2 y 3 son independientes entre sí, ¿es prudente dejar que el fragmento 2 espere hasta que el fragmento 3 termine de ejecutarse? ¿No sería más eficiente si nuestro fragmento de código 3, que consume muchos recursos, se ejecutara de alguna manera en un subproceso separado? De esta forma, los fragmentos de código 1 y 2 se ejecutan en un subproceso, pero el 3 se ejecuta en paralelo en un subproceso diferente. De eso se tratan las rutinas. «Co» significa juntos, «rutinas» es otro nombre para una función. Está en los nombres de las personas.
Pero, ¿por qué necesitamos rutinas? En nuestro ejemplo anterior, ¿por qué necesitamos que nuestro hilo se publique lo antes posible? No es el hilo principal, es solo un hilo de trabajo. Entonces, ¿cuál es el problema? El problema es que en una aplicación profesional es necesario realizar muchas tareas paralelas. Ahora podría argumentar: ¿por qué no seguir creando nuevos hilos para cada cálculo paralelo? Porque la creación de subprocesos es una operación que consume muchos recursos. Además, los hilos son objetos que residen en la memoria después de todo. Cada subproceso de Java tiene su propia pila, generalmente de 1 MB. (64k es el espacio de pila mínimo permitido en la JVM). Por lo tanto, no puede crear nuevos hilos en cualquier momento y en cualquier lugar. Los grupos de subprocesos resuelven este problema. Como sugiere el nombre, un grupo de subprocesos es una colección de subprocesos reutilizables. Cuando una aplicación necesita un nuevo subproceso, simplemente toma un subproceso libre del grupo, lo ejecuta y devuelve el subproceso al grupo. Pero esto aún puede ser un problema cuando hay demasiadas tareas paralelas para ejecutar. Las corrutinas resuelven este problema. Puede tener cualquier cantidad de rutinas en su aplicación (cada rutina suele tener solo unas pocas docenas de bytes). Una corrutina persiste en un subproceso hasta que alcanza un punto de pausa (que trataremos en un artículo futuro), momento en el que deja el subproceso y lo libera, lo que le permite ejecutar otras corrutinas mientras espera. De esta forma, el número de subprocesos es limitado, por lo que se utiliza menos memoria y se puede realizar más trabajo simultáneo.
Esta es una simplificación excesiva de un tema aparentemente complejo. Pero el propósito de esta publicación es resaltar claramente la diferencia entre rutinas e hilos y por qué las rutinas no son hilos livianos. En futuros artículos, profundizaremos en Coroutines, cómo iniciarlos, suspender funciones, CoroutineScope, CoroutineContext y más. Un montón de cosas por venir.
Borracho, si todavía estás leyendo, ¡vete a la cama!
¡Paz!