⚙️ Procesos e hilos

M0490 · Programación de servicios y procesos · Resumen fácil + quiz

1 Conceptos básicos

📄 ProgramaSerie de instrucciones guardada como archivo en disco. Está "quieto".
🏃 ProcesoUn programa en ejecución. Vive en la RAM y usa la CPU.
🧵 Hilo (fil / thread)Unidad mínima de ejecución dentro de un proceso. Comparte memoria con los otros hilos.
🔧 ServicioProceso en segundo plano (background), sin interacción con el usuario (servidor web, cola de impresión…).

PCB (Process Control Block)

Cada proceso tiene un PCB con lo que el SO necesita para ejecutarlo:

Qué hace el SO al ejecutar una app

Proceso vs hilo (la diferencia clave)

ProcesoHilo
MemoriaPropia, aisladaCompartida con su proceso
CostePesado, caro de crearLigero, rápido
SeguridadMás seguro (no corrompe a otros)Si un hilo falla, puede tumbar todo el proceso
ProblemaComunicarse cuesta más (IPC)Hay que sincronizar
Todo proceso tiene como mínimo 1 hilo. Con 1 hilo = monohilo; con varios = multihilo.
Ej.: un navegador (proceso) con un hilo para la interfaz, otro para descargas y otro para la música.

Ventajas e inconvenientes de los hilos

2 Estados de un proceso y planificación

Nuevo→ Preparado⇄ Ejecución→ Finalizado

Planificadores

Hay más procesos que CPUs, así que el planificador decide quién se ejecuta y cuándo.

TipoQué hace
Largo plazoPasa programas del disco a memoria (los convierte en procesos).
Medio plazoSuspende/reanuda procesos; mueve a la zona de intercambio (swap) si el sistema está saturado.
Corto plazo (CPU)Elige qué proceso preparado entra a la CPU. El más importante para el rendimiento.

Algoritmos de planificación

AlgoritmoIdea👍👎
FCFS (First Come First Served)El primero que llega, primero que se ejecutaSimpleUno largo hace esperar a todos (efecto convoy)
SJN (Shortest Job Next)Primero el más cortoTiempo medio de respuesta bajoPerjudica a los largos
Round RobinCada uno tiene un tiempo fijo (quantum); si no acaba, al final de la colaEquitativoQuantum corto → muchos cambios de contexto; largo → se parece a FCFS
PrioridadesSiempre el de más prioridadAtiende lo urgenteInanición: los de baja prioridad esperan siempre

3 Concurrencia, paralelismo y distribución

Objetivos de la concurrencia

Paralela vs distribuida

ParalelaDistribuida
DóndeVarios núcleos de un mismo ordenadorVarios ordenadores en red
MemoriaCompartida (misma RAM)Cada máquina la suya
ComunicaciónMemoria compartidaPor red
EjemploProcesar una imagen con 4 núcleosGoogle Search, torrent (P2P), juegos online

Problemas típicos

🏁 Condición de carreraDos hilos tocan la misma variable a la vez y el resultado depende del orden → incorrecto.
🔒 Interbloqueo (deadlock)Cada uno espera un recurso que tiene bloqueado el otro → se quedan parados para siempre.
😴 Inanición (starvation)Uno de baja prioridad nunca llega a ejecutarse.

4 Gestión de procesos e IPC

Linux / UnixPara qué
ps / ps -efProcesos activos (con PID y PPID)
top / htopLista en tiempo real (htop = más visual)
kill PIDEnvía señal SIGTERM (pide parar)
kill -9 PIDSIGKILL: lo mata al instante
jobs, fg, bgPrimer / segundo plano en la shell
Windows
Administrador de tareasVer y finalizar procesos
tasklistListar procesos
taskkill /PID <pid>Finalizar un proceso

IPC (Inter-Process Communication)

Cómo se pasan datos los procesos. Técnicas: ficheros y pipes (sencillas), sockets, memoria compartida y colas de mensajes (más potentes).

Ejemplo de pipe: ls | grep .java → la salida de un proceso es la entrada del otro.
Se elige según: ¿local o distribuida? ¿velocidad o persistencia? ¿acoplamiento fuerte o débil?

Sincronización entre procesos

Ejemplo clásico de carrera: cuenta con 100 €. A ingresa +50, B retira −30. Ambos leen 100 a la vez → A escribe 150, B escribe 70 → queda 70 € en lugar de 120 €.

5 Procesos en Java

Runtime

Process p = Runtime.getRuntime().exec("notepad");  // lanza un proceso externo
p.waitFor();                                      // espera a que acabe

Métodos de Process

MétodoQué hace
getInputStream()Leer la salida estándar del proceso (lo que imprime)
getOutputStream()Escribir en su entrada estándar (como el teclado)
getErrorStream()Leer su salida de error
waitFor()Esperar a que termine
exitValue()Código de salida
Ojo con el nombre: getInputStream() lee la salida del proceso (es "input" desde el punto de vista de Java).

ProcessBuilder (el recomendado)

Más control de argumentos, permite redirigir entrada/salida y es más claro.

ProcessBuilder pb = new ProcessBuilder("ls", "-l");   // orden y argumentos separados
pb.redirectOutput(new File("salida.txt"));          // también redirectInput / redirectError
Process p = pb.start();                             // ejecuta

Pipes en Java: conectar la salida de un proceso (ls / dir) a la entrada de otro (grep / findstr). Java lo automatiza con ProcessBuilder.startPipeline(...).

6 Hilos en Java

Todo programa Java empieza con el hilo principal (main thread). Dos formas de crear hilos:

// 1) Heredar de Thread
class MiHilo extends Thread {
    public void run() { System.out.println("Hola desde un hilo"); }
}
new MiHilo().start();

// 2) Implementar Runnable  (⭐ recomendada)
class MiTarea implements Runnable {
    public void run() { System.out.println("Hola"); }
}
new Thread(new MiTarea()).start();
Se llama a start(), NUNCA a run() directamente: si llamas a run() se ejecuta en el mismo hilo, no en uno nuevo.

Por qué Runnable es mejor: tu clase puede heredar de otra a la vez (Java no tiene herencia múltiple) y se reutiliza mejor el código.

Control de hilos

MétodoQué hace
sleep(ms)Pausa el hilo X milisegundos y libera la CPU
join()El padre espera a que el hijo termine
interrupt()Pide que pare (no lo mata). No usar stop(): deja recursos abiertos
setPriority(n)Prioridad de 1 (MIN) a 10 (MAX). Por defecto 5 (NORM)

Los estados de un hilo están en el enum Thread.State: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.

7 Sincronización de hilos

// Método sincronizado: bloquea el objeto entero
public synchronized void incrementar() { count++; }

// Bloque sincronizado: solo bloquea la parte crítica (más eficiente)
public void incrementar() {
    synchronized (this) { count++; }
}
Monitor: en Java cualquier objeto tiene un lock. Si un hilo entra en synchronized(obj), los demás que quieran entrar en bloques sincronizados del mismo objeto esperan.

Deadlock y cómo evitarlo

Hilo 1 bloquea cuenta A y quiere B; hilo 2 bloquea cuenta B y quiere A → ninguno avanza.

Solución: establecer un orden global de bloqueo (todos bloquean siempre en el mismo orden, p. ej. por id de cuenta).

8 Comunicación entre hilos: wait() / notify()

No basta con no pisarse: a veces un hilo tiene que avisar a otro (p. ej. "ya hay datos").

synchronized (obj) {
    while (!condicion) {   // ⚠️ while, NO if
        obj.wait();
    }
    // hacer el trabajo
    obj.notifyAll();
}
Se usa while y no if porque al despertar hay que volver a comprobar la condición: puede haber cambiado antes de recuperar el lock.

Productor / Consumidor

🎮 Quiz estilo Kahoot