11 - Hilos en Tomcat

Un servidor web atiende muchas peticiones a la vez. En Tomcat, cada petición la procesa un hilo; entender cómo se reparten y reutilizan es necesario para decidir qué estado puede guardarse y dónde.

Tomcat mantiene un pool de hilos con hilos worker disponibles. Cuando llega una petición HTTP, se asigna a un hilo libre; al terminar la respuesta, el hilo vuelve al pool y puede atender otra petición.

Peticiones En qué hilos se ejecutan
Simultáneas Cada una se ejecuta en un hilo distinto
Sucesivas Pueden ejecutarse en el mismo hilo reutilizado

Cliente ACliente BCliente CTomcatHilo 1Hilo 2Cliente ACliente BCliente CTomcatHilo 1Hilo 2Cliente ACliente BCliente CTomcatHilo 1Hilo 2Petición Ala atiende el hilo 1Petición B (simultánea)la atiende el hilo 2respuestarespuestaPetición C (posterior)reutiliza el hilo 1respuesta

Un campo static pertenece a la clase: todos los hilos ven y modifican el mismo valor.

public class SharedValue {
    private static volatile String value;

    public static void setValue(String newValue) {
        value = newValue;
    }

    public static String getValue() {
        return value;
    }
}

Si dos peticiones fijan valores distintos a la vez, la segunda puede sobrescribir el valor antes de que la primera lo lea: una petición trabaja con el valor de otra. Es una condición de carrera: el resultado depende del orden temporal en que se ejecutan los hilos.

volatile no crea un valor distinto para cada hilo: el campo static sigue siendo único y compartido. La diferencia es qué garantía hay al leer escrituras de otros hilos:

Hilo A: escribe "A"
Hilo B: escribe "B"
Hilo A: lee el campo

  • Con volatile: si la escritura de B ocurre antes de la lectura de A, A ve “B”. La escritura es visible, pero el campo sigue siendo compartido.
  • Sin volatile: Java no garantiza que A vea la escritura reciente de B. Puede observar un valor antiguo; no se puede asumir que verá “A” ni que cada hilo conserve un valor propio.

En ambos casos hay acceso compartido. volatile garantiza visibilidad, pero no evita que una escritura sobrescriba otra ni hace indivisible una secuencia de operaciones. Por tanto, no evita la condición de carrera.

Campo static Variable local
Un único valor visible para todos los hilos Cada hilo tiene la suya en su propia pila
Requiere cuidado ante accesos concurrentes No se comparte entre peticiones

ThreadLocal guarda un valor distinto para cada hilo: cada hilo solo ve el suyo.

public class ThreadData {
    private static final ThreadLocal<String> DATA_BY_THREAD = new ThreadLocal<>();

    public static void setData(String data) {
        DATA_BY_THREAD.set(data);
    }

    public static String getData() {
        return DATA_BY_THREAD.get();
    }

    public static void clearData() {
        DATA_BY_THREAD.remove();
    }
}

Pero el valor es por hilo, no por petición. Como Tomcat reutiliza los hilos, el valor fijado durante una petición sigue ahí cuando el mismo hilo atiende la siguiente: la nueva petición encontraría un valor que no le corresponde. Es una fuga de datos entre peticiones.

  • clase/daw/prog/2eval/hilos.txt
  • Última modificación: 2026/10/12 10:38
  • por cesguiro