Concurrencia
La capacidad de un programa de avanzar en varias tareas a la vez, por ejemplo con varios hilos o goroutines.
Un programa concurrente reparte el trabajo en tareas que avanzan de forma intercalada o, si hay varios núcleos, a la vez (paralelismo). Así aprovecha mejor el procesador o atiende muchas peticiones.
El riesgo aparece al compartir datos: si dos hilos modifican lo mismo a la vez se producen carreras de datos y resultados imprevisibles. Para evitarlo se usan bloqueos (mutex), canales o lenguajes como Rust que lo comprueban al compilar.
Un ejemplo
Un servidor web atiende a cientos de visitantes a la vez: cada petición se procesa de forma concurrente.
Por qué importa
La concurrencia es la capacidad de un programa de manejar varias tareas que avanzan de forma solapada, como un servidor que atiende a cientos de usuarios a la vez o una aplicación que descarga un archivo mientras sigue respondiendo a la interfaz. Sin ella, cada operación lenta bloquearía todo lo demás.
Es también una de las áreas donde más errores sutiles aparecen. Cuando dos tareas acceden a los mismos datos, el resultado puede depender del orden en que se ejecuten, lo que se conoce como condición de carrera. Estos fallos son difíciles de reproducir porque no ocurren siempre.
Confusiones frecuentes
Concurrencia y paralelismo se confunden constantemente. Concurrencia consiste en gestionar varias tareas a la vez, aunque en un instante dado solo avance una, como un cocinero que alterna entre varias ollas. Paralelismo es ejecutarlas literalmente al mismo tiempo en varios núcleos. Se puede tener lo primero sin lo segundo. Otro error es pensar que más hilos siempre hacen el programa más rápido: crear demasiados puede ralentizarlo, y compartir datos exige mecanismos como cerrojos para evitar corrupción.
Preguntas frecuentes
¿Qué es un deadlock?
Un bloqueo mutuo: dos tareas esperan cada una un recurso que tiene la otra, y ninguna avanza nunca. Se evita adquiriendo los cerrojos siempre en el mismo orden.
¿Qué modelos existen?
Los principales son hilos con memoria compartida, procesos separados, código asíncrono con un bucle de eventos y paso de mensajes entre tareas, como hace Go con canales.
Fuentes consultadas
- A Tour of Go: Goroutines (go.dev)