Introducción

En esta sesión, solucionaremos una serie de problemas de casos de uso hipotéticos mediante programación concurrente para los que aplicaremos las técnicas vistas en las sesiones de teoría. Para ello, en grupos de 2 o 3 personas, resolveréis uno a uno los problemas propuestos y luego comentaremos la solución de cada uno de ellos. Para resolver los problemas podéis usar cualquiera de los mecanismos vistos en clase (candados, semáforos, monitores, variables de condicion, instrucciones atómicas, thread pools, …).

Problemas

1. Sistema de Gestión de Inventario

Un sistema de almacén tiene una única cola de pedidos (buffer) con capacidad limitada $N$. Hay hilos Productores que crean pedidos de distintos tipos ($A$, $B$, $C$). Hay hilos Consumidores especializados: un grupo solo procesa pedidos de tipo $A$, otro solo de tipo $B$, y un tercero solo de tipo $C$.

Realiza una implementación en pseudocódigo del sistema.

2. Sistema de Gestión de Base de Datos con Administrador global

Una base de datos tiene miles de hilos Lectores y hilos Escritores (de transacciones individuales). Periódicamente, un único hilo Administrador necesita realizar una Actualización Global (ej. una limpieza o reindexación) que toma mucho tiempo. GoGo

Implementa una política de proridad que asegure que el Administrador no sufra inanición y que los procesos ya iniciados terminen antes de que el bloqueo ocurra.

3. Peaje con Múltiples Cabinas

Un peaje tiene $M$ carriles por donde pasan los vehículos, cada uno con una cabina de cobro. Cada cabina solo puede ser ocupada por un coche a la vez (Exclusión Mutua). El peaje quiere maximizar el flujo y lleva un contador global de vehículos que han pasado.

Propón una solución al sistema asumiendo que los coches son hilos, puedan seleccionar el carril que quieran utilizar, acceder a la cabina, pagar (incrementando también el contador) y salir.

4. El Puente de un Solo Sentido

Un puente de un solo carril conecta dos ciudades $A$ y $B$. Los coches de la Ciudad $A$ y los coches de la Ciudad $B$ quieren cruzar. El puente solo puede tener coches de un sentido a la vez. Una vez que un coche de un sentido entra, puede entrar cualquier otro coche de ese mismo sentido hasta que ya no queden.

Hay semáforos (de tráfico) en las entradas al puente y también 2 sensores para detectar si hay vehículos esperando en los semáforos y 2 más para comprobar si han pasado por alguna de las salidas. Implementa la lógica de control de los semáforos teniendo en cuenta los requerimientos dados.

5. Renderizado Paralelo

Una imagen 3D es renderizada por $N$ hilos. El proceso tiene 3 fases secuenciales que deben completarse: Geometría, Iluminación y Texturizado. Cada fase es computada en paralelo por los $N$ hilos.

Propón una implementación en pseudocódigo a este problema teniendo en cuenta que ningún hilo puede empezar una fase sin que los $N$ hayan finalizado la anterior.

6. Buffer de Múltples Sensores

Un sistema de Productores-Consumidores tiene una úncia cola de mensajes de una capacidad $N$. Hay dos tipos de Productores: Sensores de Temperatura ($T$) y Sensores de Presión ($P$). Hay dos tipos de Consumidores: Hilos que solo leen $T$ y Hilos que solo leen $P$.

Implementa una solución al problema de tal manera que, cuando un productor $T$ inserta un mensaje, solo debe despertar a un consumidor $T$ (si hay alguno esperando). No debería despertar a todos los consumidores $P$.

7. Secuenciador de Arranque de Módulos

Un sistema complejo tiene 4 módulos (A, B, C, D) que deben inicializarse concurrentemente. Sin embargo, existen dependencias:

  • Módulo A y Módulo B pueden arrancar en paralelo.
  • Módulo C solo puede arrancar si A y B han terminado su inicialización.
  • Módulo D solo puede arrancar si C ha terminado su inicialización.

Implementa un sistema para coordinar el arranque de todos los hilos/procesos para asegurar que las dependencias de inicialización se cumplan estrictamente.

8. Modelo de Despacho de Eventos

En un servidor de alto rendimiento, un único hilo Despachador recibe eventos (ej. paquetes de red). Estos eventos deben ser encolados y procesados por un pool de Hilos Trabajadores. Sin embargo, la prioridad es alta: los eventos deben procesarse en el orden exacto en que fueron recibidos. Aunque el procesamiento es concurrente, el inicio del procesamiento debe respetar el orden. Si el Hilo Trabajador $T_1$ termina el evento 5, no puede empezar a procesar el evento 6 si el Hilo Trabajador $T_2$ aún no ha terminado el evento 4.

Realiza una implementación a este sistema asegurando que la finalización de los eventos se realiza de manera secuencia