Unidad 4

Condiciones de carrera y concurrencia

¿Qué pasa cuando todos quieren lo mismo?

Situaciones cotidianas

  • Varios estudiantes quieren usar la misma impresora
  • Dos personas mandan un mensaje a la vez en un chat grupal
  • Múltiples autos llegan a un SEMÁFORO al mismo tiempo
  • Dos personas editan el mismo documento en Drive

¿Quién pasa primero? ¿Qué pasa si chocan?

En computación: lo mismo, pero con procesos

  • Procesos = Los estudiantes (cada programa en ejecución)
  • Recursos compartidos = La impresora, la memoria, el archivo
  • Concurrencia = Varios procesos quieren los mismos recursos
  • Sincronización = Las reglas para evitar el caos

Hoy vamos a pensar sobre estos problemas, no a programarlos todavía.

Procesos e Hilos

¿Qué es un Proceso?

Un proceso es un programa en ejecución.

  • Tu navegador Chrome abierto = un proceso
  • Word abierto = otro proceso
  • Spotify reproduciendo = otro más

Cada proceso tiene su propia memoria separada.

¿Qué es un Hilo (Thread)?

Un hilo es una tarea dentro de un proceso.

  • En Chrome: una pestaña puede ser un hilo
  • En Word: el corrector ortográfico puede ser otro hilo

Diferencia clave: los hilos de un mismo proceso comparten recursos entre sí.

Analogía: Casa vs. Personas

PROCESO = Casa
├── HILO 1 = Persona cocinando
├── HILO 2 = Persona limpiando
└── HILO 3 = Persona estudiando

Todos en la misma casa (comparten cocina, baño, living)
→ ¡Si dos quieren usar el horno, hay que coordinarse!
                

Concurrencia vs. Paralelismo

Concurrencia: Turnarse

Un chef hace múltiples tareas intercalándolas:

Minuto 1-2: Pica cebolla
Minuto 3-4: Revisa el horno
Minuto 5-6: Sigue picando
Minuto 7-8: Revisa el horno de nuevo
                

Una persona, múltiples tareas, se va turnando.

Paralelismo: Simultáneo

Dos chefs trabajan al mismo tiempo:

Chef A: Pica cebolla continuamente
Chef B: Vigila el horno continuamente
                

Dos personas, dos tareas, en verdadero paralelo.

¿Por qué importa la diferencia?

  • Paralelismo: Necesitás varias CPUs (o núcleos)
  • Concurrencia: Solo con 1 CPU podés lograr intercalar tareas

La mayoría de las veces en este curso hablamos de concurrencia: cómo se turnan los procesos para compartir un recurso.

Condiciones de Carrera

¿Qué es una Condición de Carrera?

Una condición de carrera (race condition) ocurre cuando el resultado depende del orden de ejecución.


El resultado varía según quién llegue primero.

Ejemplo: El Último Asiento del Cine

Situación: 1 asiento libre en la sala

Persona A:                    Persona B:
1. Mira la pantalla          1. Mira la pantalla
2. Ve "1 asiento libre"     2. Ve "1 asiento libre"
3. Decide comprar            3. Decide comprar
4. Presiona "Comprar"        4. Presiona "Comprar"

→ ¡El sistema vendió 2 entradas para 1 asiento!
                

Ejemplo: La Cuenta Compartida

María y José comparten una cuenta con $1000.


Depósito de María (+$500):

1. Leer saldo actual → $1000
2. Calcular nuevo saldo → $1000 + $500 = $1500
3. Guardar nuevo saldo → $1500
                

Retiro de José (-$300):

1. Leer saldo actual → $1000
2. Calcular nuevo saldo → $1000 - $300 = $700
3. Guardar nuevo saldo → $700
                

¿Qué pasa si se ejecutan "a la vez"?

t=0: SALDO = $1000

t=1: María lee saldo → obtiene $1000
t=2: José lee saldo → obtiene $1000 (¡María aún no escribió!)
t=3: María calcula → $1000 + $500 = $1500
t=4: José calcula → $1000 - $300 = $700
t=5: María guarda → SALDO = $1500
t=6: José guarda → SALDO = $700

→ ¡El depósito de María se perdió!
                

Resultado esperado: $1200 | Resultado real: $700

¿Por qué pasa esto?

La operación saldo = saldo + 500 NO es atómica. Necesita 3 pasos:


1. LEER el valor actual
2. SUMAR
3. ESCRIBIR el resultado
                

Si dos procesos leen al mismo tiempo, se sobrescriben mutuamente.

Ejercicio mental: El Contador

contador = 0

Persona A: hacer 1000 veces { contador = contador + 1 }
Persona B: hacer 1000 veces { contador = contador + 1 }

¿Resultado esperado? 2000
¿Resultado real? Cualquier número entre 1000 y 2000
                

Cada incremento pierde datos por el mismo problema de lectura/escritura entrelazada.

Sección Crítica

¿Qué es una Sección Crítica?

Una sección crítica es la parte del código donde se accede a un recurso compartido.


Regla de oro: Solo UN proceso/hilo puede ejecutar la sección crítica a la vez.

Analogía: El Baño Compartido

SECCIÓN CRÍTICA = Estar dentro del baño

Protocolo:
1. Intentar entrar (verificar si está libre)
2. Si está libre → Entrar y CERRAR CON LLAVE
3. Usar el baño
4. Salir y ABRIR LA PUERTA

La llave = Mecanismo de sincronización
                

Estructura General

PROTOCOLO DE ENTRADA
    (pedir permiso, esperar si es necesario)

SECCIÓN CRÍTICA
    (acceder al recurso compartido)

PROTOCOLO DE SALIDA
    (liberar el recurso para otros)

RESTO DEL CÓDIGO
    (trabajo que no necesita el recurso)
                

Semáforos

El Semáforo: Un Guardián

Un semáforo es un guardia que controla cuántas personas pueden entrar.


  • WAIT (esperar): "¿Puedo pasar?" → Si contador > 0, decrementar y pasar. Si no, esperar.
  • SIGNAL (señalar): "Ya terminé" → Incrementar contador, despertar a alguien si espera.

Ejemplo: Estacionamiento

ESTACIONAMIENTO CON 3 ESPACIOS
Semáforo iniciado con valor = 3

Auto 1: ESPERAR → contador baja a 2 → Entra
Auto 2: ESPERAR → contador baja a 1 → Entra
Auto 3: ESPERAR → contador baja a 0 → Entra
Auto 4: ESPERAR → contador = 0 → ¡DEBE ESPERAR!
Auto 1 sale: SEÑALAR → contador sube a 1 → Auto 4 puede entrar
                

Tipos de Semáforos

Semáforo Binario (Mutex)

  • Valores: solo 0 o 1
  • Uso: Proteger secciones críticas
  • Equivalente: Un baño con una sola persona


Semáforo Contador

  • Valores: 0, 1, 2, 3, ...
  • Uso: Recursos múltiples limitados
  • Equivalente: Estacionamiento con N espacios

Solución a la Cuenta Compartida

SEMÁFORO mutex = 1 (inicialmente libre)

Depósito:
  1. WAIT(mutex)        ← Pedir permiso
  2. Leer saldo
  3. Calcular nuevo saldo
  4. Guardar nuevo saldo
  5. SIGNAL(mutex)       ← Liberar para otros

Retiro:
  1. WAIT(mutex)        ← Pedir permiso
  2. Leer saldo
  3. Calcular nuevo saldo
  4. Guardar nuevo saldo
  5. SIGNAL(mutex)       ← Liberar para otros
                

Ahora NO puede haber race condition porque solo uno accede a la vez.

Problemas Clásicos de Sincronización

Los Filósofos Comensales

Cinco filósofos sentados en una mesa circular. Entre cada par hay un palito. Para comer, cada filósofo necesita DOS palitos.


Cena de los filósofos

Ciclo de vida de un filósofo

REPETIR SIEMPRE:
  - PENSAR (no necesita palitos)
  - Tomar palito izquierdo
  - Tomar palito derecho
  - COMER
  - Soltar palito izquierdo
  - Soltar palito derecho
                

Problema: Deadlock

¿Qué pasa si todos toman su palito izquierdo "a la vez"?

t=1: F1 toma Palito 1
t=2: F2 toma Palito 2
t=3: F3 toma Palito 3
t=4: F4 toma Palito 4
t=5: F5 toma Palito 5

→ ¡Todos esperan el palito derecho que ya está tomado!
→ DEADLOCK: Nadie puede avanzar, todos bloqueados
                

Problema: Inanición

Imagina que F1 y F2 comen muy rápido y se turnan constantemente.


F3, F4 y F5 nunca logran conseguir ambos palitos.


Inanición: algunos filósofos esperan infinitamente mientras otros se turnan.

Posibles Soluciones

Solución 1: Orden asimétrico

Filósofos impares (F1, F3, F5): Primero izquierdo, luego derecho
Filósofos pares (F2, F4): Primero derecho, luego izquierdo
→ Rompe la simetría, previene deadlock
                

Solución 2: Máximo de comensales

Máximo 4 filósofos pueden intentar comer simultáneamente
→ Siempre al menos uno podrá tomar ambos palitos
                

Deadlock

¿Qué es un Deadlock?

Situación donde dos o más procesos están bloqueados permanentemente, esperando recursos que otros tienen.


CRUCE DE CALLES:

Auto A viene del Norte, quiere ir al Sur
Auto B viene del Este, quiere ir al Oeste

Ambos llegan al cruce simultáneamente:
→ A espera que B avance
→ B espera que A avance
→ DEADLOCK: Ninguno puede avanzar
                

Las 4 Condiciones de Coffman

Para que haya deadlock, deben cumplirse las 4:


  • 1. Exclusión Mutua: El recurso no puede compartirse
  • 2. Retención y Espera: Un proceso retiene recursos mientras espera otros
  • 3. No Apropiación: No se pueden quitar recursos por la fuerza
  • 4. Espera Circular: Cadena circular de esperas

Estrategias de Manejo

  • Prevención: Eliminar una de las 4 condiciones
  • Evitación: Algoritmo del Banquero (verificar estado seguro antes de asignar)
  • Detección y recuperación: Permitir deadlock, detectarlo y romperlo
  • Ignorar el problema: Asumir que deadlock es raro (¡muchos SO reales!)

Resumen

Conceptos clave de hoy

  • Proceso = Programa en ejecución (memoria propia)
  • Hilo = Tarea dentro de un proceso (comparte memoria)
  • Race condition = Resultado depende del orden de ejecución
  • Sección crítica = Código que accede a recurso compartido
  • Semáforo = Mecanismo de sincronización (WAIT + SIGNAL)
  • Mutex = Semáforo binario (0 o 1)
  • Deadlock = Bloqueo mutuo permanente
  • Inanición = Proceso espera infinitamente