L'execució no bloquejant és un model d'execució en què una operació que pot trigar un temps indeterminat, com ara una operació d'entrada/sortida, una comunicació de xarxa o una consulta a una base de dades, no atura completament el progrés del programa mentre s'espera el resultat. En lloc de romandre inactiu fins que l'operació finalitza, el programa pot continuar executant altres tasques i reprendre l'operació pendent quan el resultat ja està disponible.Fowler, Matthew. Python Concurrency with asyncio. Shelter Island, New York: Manning Publications, 2022. ISBN 9781617298660.

Aquest model és habitual en sistemes que han de gestionar moltes operacions concurrents, com ara servidors web, aplicacions de xarxa, microserveis o sistemes que fan servir programació asíncrona. L'execució no bloquejant és especialment rellevant en càrregues de treball limitades per entrada/sortida, en què el temps d'espera d'una resposta externa pot ser molt superior al temps de càlcul local.

Funcionament En una execució bloquejant, una crida a una operació lenta manté aturat el fil d'execució fins que l'operació acaba. Per exemple, si un programa espera dades d'un sòcol de xarxa, no pot continuar executant altres instruccions mentre la lectura resta pendent. Aquest comportament és senzill de programar, però pot limitar la capacitat de resposta del sistema quan hi ha moltes operacions independents.

En una execució no bloquejant, la crida retorna el control al programa encara que l'operació no hagi acabat. El sistema d'execució registra l'operació pendent i permet que altres parts del programa continuïn avançant. Quan l'operació ja pot produir un resultat, el programa és notificat i pot reprendre el tractament de les dades.

En molts sistemes, aquesta coordinació es fa mitjançant un bucle d'esdeveniments. En el cas de Python, la documentació d'asyncio descriu el bucle d'esdeveniments com el nucli de les aplicacions asíncrones, encarregat d'executar tasques, callbacks, operacions d'entrada/sortida de xarxa i subprocessos.

Relació amb la concurrència L'execució no bloquejant és una tècnica per aconseguir concurrència, però no implica necessàriament paral·lelisme. En un sistema concurrent, diverses tasques poden estar en curs al mateix temps, encara que només una estigui executant codi en un instant determinat. En canvi, el paral·lelisme requereix que dues o més tasques s'executin físicament alhora, normalment en diversos nuclis de processador.

En models com el d'asyncio, una tasca pot suspendre's quan arriba a una operació d'entrada/sortida pendent. Mentre aquesta operació espera una resposta del sistema operatiu o d'un servidor extern, el bucle d'esdeveniments pot executar altres tasques que estiguin preparades. Quan la resposta arriba, la tasca suspesa es reprèn des del punt on havia cedit el control.

Aquesta forma d'execució permet aprofitar millor els temps d'espera. Per exemple, un servidor pot iniciar una lectura de xarxa per a un client, continuar atenent altres connexions i tornar a la primera connexió quan les dades ja són disponibles.

Entrada/sortida no bloquejant Un dels casos més habituals d'execució no bloquejant és l'entrada/sortida no bloquejant. Els sòcols de xarxa, per exemple, són bloquejants per defecte en molts entorns: una lectura pot aturar el programa fins que hi hagi dades disponibles. En mode no bloquejant, la crida no espera indefinidament; si encara no hi ha dades, retorna immediatament o indica que l'operació no es pot completar en aquell moment.

Els sistemes operatius proporcionen mecanismes per detectar quan un descriptor de fitxer o un sòcol està preparat per llegir o escriure. En Python, el mòdul selectors ofereix una interfície d'alt nivell per esperar de manera eficient notificacions de preparació d'entrada/sortida sobre diversos objectes.

Ús en programació asíncrona En la programació asíncrona, l'execució no bloquejant s'expressa sovint mitjançant corutines, tasques i operacions esperables. Una corutina pot cedir el control quan arriba a una operació pendent i continuar més endavant, sense bloquejar el conjunt de l'aplicació. Aquest model és habitual en biblioteques de xarxa, clients HTTP asíncrons, controladors de bases de dades no bloquejants i servidors capaços de mantenir moltes connexions simultànies.

L'avantatge principal és que es poden gestionar moltes operacions d'entrada/sortida amb un nombre reduït de fils d'execució. Això pot reduir el cost associat a la creació i commutació de fils, i pot millorar la capacitat de resposta en aplicacions amb moltes esperes externes.

Limitacions L'execució no bloquejant no millora automàticament qualsevol tipus de programa. És especialment útil quan el coll d'ampolla és l'entrada/sortida, però pot no aportar beneficis en tasques limitades pel processador, com ara càlculs numèrics intensius o processament massiu de dades. En aquests casos, si el codi ocupa el processador durant períodes llargs sense cedir el control, pot impedir que el bucle d'esdeveniments executi altres tasques.

També cal evitar barrejar codi asíncron amb biblioteques bloquejants sense cap mecanisme d'adaptació. Una crida bloquejant dins d'una tasca asíncrona pot aturar el fil que executa el bucle d'esdeveniments i reduir o anul·lar els avantatges de l'execució no bloquejant.

Vegeu també Programació asíncrona Concurrència Entrada/sortida Bucle d'esdeveniments

Referències

Categoria:Informàtica