Problemas de concurrencia y sincronización
La concurrencia ocurre cuando varios procesos o hilos se ejecutan al mismo tiempo (o parecen hacerlo) y comparten recursos. 👉 El reto: coordinar su ejecución para evitar errores.
1. Problemas comunes de concurrencia #
-
Condiciones de carrera (race conditions)
- Se producen cuando dos o más procesos acceden y modifican un recurso compartido al mismo tiempo, y el resultado depende del orden de ejecución.
- Ejemplo: dos cajeros actualizando el saldo de la misma cuenta bancaria.
-
Secciones críticas
- Son fragmentos de código donde un proceso accede a un recurso compartido.
- Si dos procesos entran a la vez en su sección crítica → error.
-
Interbloqueo (deadlock)
- Dos o más procesos quedan bloqueados esperando recursos que nunca se liberan.
- Ejemplo: el proceso A tiene el recurso X y espera el recurso Y, mientras que el proceso B tiene el recurso Y y espera el recurso X.
-
Inanición (starvation)
- Un proceso nunca obtiene CPU o recursos porque otros de mayor prioridad siempre se adelantan.
-
Bloqueo activo (busy waiting)
- Un proceso espera ocupando CPU en lugar de quedar en pausa, desperdiciando recursos.
2. Mecanismos de sincronización #
-
Bloqueos (locks / mutexes)
- Permiten que solo un proceso o hilo acceda a un recurso a la vez.
-
Semáforos
- Contadores que regulan el acceso a recursos con capacidad limitada.
- Ejemplo: un semáforo en una base de datos permite que solo 5 usuarios abran conexiones simultáneas.
-
Monitores
- Abstracción de más alto nivel que combina bloqueo + variables de condición.
- Muy usados en lenguajes de programación modernos (Java, C#).
-
Variables de condición
- Permiten que un proceso espere hasta que otro libere un recurso.
3. Ejemplo práctico #
-
Banco con cuentas compartidas:
- Dos cajeros intentan actualizar la misma cuenta al mismo tiempo.
- Si no hay control, el saldo puede quedar mal calculado (condición de carrera).
- Solución: usar un mutex para que solo un cajero pueda modificar la cuenta a la vez.
Resumen del tema
Conceptos clave #
- Condiciones de Carrera (Race Conditions): anomalía donde el resultado final depende del orden temporal impredecible de acceso a memoria compartida.
- Problema de la Sección Crítica: fragmento de código que manipula recursos compartidos y que debe cumplir tres requisitos: exclusión mutua, progreso y espera limitada.
- Primitivas de Sincronización:
- Mutex (Mutual Exclusion Lock): cerrojo binario poseído por un único hilo para garantizar exclusión mutua.
- Semáforos (Dijkstra): variables enteras atómicas con operaciones
wait() / P()ysignal() / V()para control de recursos finitos o señalización. - Monitores: construcciones de alto nivel que encapsulan datos compartidos, exclusión mutua implícita y variables de condición.
- Patologías Concurrentes: inanición (starvation), espera activa (busy waiting / spinlocks) e interbloqueos (deadlocks).
Qué debes recordar #
Para evitar condiciones de carrera en secciones críticas se requiere exclusión mutua mediante mutexes, semáforos o monitores, previniendo inanición y deadlocks.