En informàtica, la concurrència en un sol fil (en anglès, single-threaded concurrency) és un model de concurrència en què diverses tasques progressen de manera intercalada dins d'un únic fil d'execució, sense fer servir el paral·lelisme. A diferència de la multitasca apropiativa, on el sistema operatiu pot interrompre una tasca en qualsevol moment, en aquest model les tasques cedeixen el control voluntàriament quan arriben a un punt d'espera.

Funcionament El model es fonamenta en la multitasca cooperativa: cada tasca s'executa fins que troba un punt d'espera —normalment una operació d'entrada/sortida, com llegir dades d'una connexió de xarxa o esperar la resposta d'una base de dades— i aleshores retorna el control a un bucle d'esdeveniments. Aquest bucle comprova quines tasques poden continuar i les reprèn quan l'operació que esperaven ha acabat.

Des del punt de vista del programador, cada tasca sembla que s'executa de manera independent, però en realitat s'alternen en un sol fil. Una conseqüència important és que, com que en tot moment només s'executa una tasca, no cal cap mecanisme de sincronització per protegir l'estat compartit. Això evita moltes de les condicions de cursa habituals en programació concurrent i fa que el codi sigui més fàcil de seguir i de depurar. Entre dos punts d'espera consecutius, cap altra tasca no pot modificar l'estat del programa.

Relació amb el bloqueig global de l'intèrpret En el cas de Python, aquest model té una relació directa amb el bloqueig global de l'intèrpret (GIL, de l'anglès Global Interpreter Lock). El GIL impedeix que diversos fils s'executin simultàniament dins del mateix procés de CPython, cosa que fa que el multifil no sigui eficient per a tasques limitades per la CPU. El model de concurrència en un sol fil amb asyncio evita aquest problema perquè no necessita múltiples fils: totes les tasques comparteixen un únic fil i el GIL no suposa cap restricció addicional.

Avantatges i limitacions Aquest model és especialment eficient en aplicacions limitades per entrada/sortida, com ara servidors web, proxies o clients de xarxa, on la major part del temps s'espera que arribin dades externes. En aquests casos, un sol fil pot gestionar centenars de connexions simultànies sense la sobrecàrrega de memòria i de canvi de context que implica crear un fil per a cadascuna.

El punt feble és que no aprofita els processadors amb múltiples nuclis. A més, una tasca que faci un càlcul intens sense cedir el control atura totes les altres fins que acaba. En aquests casos és preferible el multiprocessament o la combinació dels dos models: diversos processos, cadascun amb el seu propi bucle d'esdeveniments.

Cal tenir en compte també que aquest model exigeix que totes les operacions d'entrada/sortida siguin no bloquejants. Si es crida una funció que bloqueja el fil —com llegir un fitxer amb les funcions estàndard del sistema operatiu— el bucle d'esdeveniments queda aturat i cap altra tasca no pot avançar.

Aplicacions Aquest model és la base d'asyncio de Python i de Node.js, i en general de qualsevol servidor orientat a esdeveniments d'alt rendiment. La sintaxi async/await, present en molts llenguatges actuals com Python, JavaScript o Kotlin, és la manera més habitual d'expressar tasques cooperatives de forma llegible sense haver de gestionar el bucle d'esdeveniments directament.

Vegeu també Bucle d'esdeveniments Programació asíncrona Multitasca cooperativa

Referències

Categoria:Programació