La concurrencia y el paralelismo vienen acompañados de ideas equivocadas que pueden llevar a diseños ineficientes o inseguros. Despejar estos mitos ayuda a elegir las herramientas correctas y a establecer expectativas realistas sobre rendimiento y corrección.
Analizamos cuatro creencias comunes y explicamos por qué son incorrectas o incompletas, junto con el enfoque adecuado.
Agregar hilos no garantiza acelerar un programa. Si el trabajo es I/O-bound, demasiados hilos generan más cambios de contexto y contención por recursos. Si es CPU-bound, más hilos que núcleos provocan que el sistema invierta tiempo cambiando de tarea en lugar de ejecutar código útil.
El número óptimo depende de la naturaleza de la carga y del hardware. Medir y perfilar es esencial antes de aumentar la cantidad de hilos; a veces un modelo asíncrono con pocos hilos es más eficiente.
Son conceptos relacionados pero distintos. La concurrencia organiza tareas que pueden solaparse en el tiempo; el paralelismo las ejecuta simultáneamente en múltiples unidades de cómputo. Un sistema puede ser concurrente en un solo núcleo sin ejecutar nada al mismo tiempo, y puede ser paralelo en cálculos aislados sin requerir coordinación compleja.
Confundirlos lleva a elegir mal la solución: usar hilos para E/S ligera puede ser innecesario si un bucle de eventos basta; intentar paralelizar código con dependencias estrechas puede no aportar beneficio.
Colocar locks en todas partes no es la respuesta. Sincronizar en exceso introduce contención, reduce el paralelismo y puede causar deadlocks. Además, no resuelve errores de diseño como compartir estado sin necesidad o elegir estructuras no aptas para concurrencia.
La estrategia correcta es minimizar el estado compartido, usar estructuras diseñadas para concurrencia (colas seguras, actores) y aplicar sincronización solo donde sea imprescindible, evaluando su costo.
En programas concurrentes, asumir un orden fijo es un error. El planificador decide cuándo y cuánto ejecuta cada tarea; los interleavings pueden variar en cada corrida. Incluso con las mismas entradas, el resultado puede cambiar si hay condiciones de carrera o dependencias temporales.
El diseño debe aceptar no determinismo: proteger secciones críticas, usar operaciones atómicas y definir invariantes que no dependan de un orden específico. Las pruebas deben contemplar resultados equivalentes y forzar escenarios de alta concurrencia para revelar problemas ocultos.
Desmontar estos mitos permite construir sistemas más seguros y eficientes: medir antes de optimizar, elegir el modelo adecuado y diseƱar pensando en no determinismo.