Programación Concurrente Curso 02-03 Relación de ejercicios SEMÁFOROS SEM.1 Supongamos que queremos controlar el acceso a un parking con el siguiente comportamiento: cuando un coche llega al parking éste espera espera a que la barrera de acceso al parking se levante. La barrera sólo se levantará cuando el parking no esté lleno, el semáforo que está detrás está verde y la máquina de tickets ha expendido un ticket. La barrera baja cuando detecta que el coche ha pasado. La máquina de tickets expende un ticket cuando detecta que se ha pulsado el botón de la máquina. Cuando la barrera está levantada entonces el coche pasa. Después de pasar el coche, la barrera se baja. Pasado un tiempo desde que el coche aparcó, éste sale del parking. Se pide resolver este problema utilizando semáforos. Se consideran 4 procesos: coche, maquinaTickets, barrera y semaforo. Como ejemplo se proporciona el pseudocódigo del proceso coche: proceso Coche; (* protocolo de entrada, uso de semáforos *) (* coche estaciona *) sleep (1000); (* el coche sale *) (* protocolo de salida, uso de semáforos *) finProcesoCoche Notas: - No olvidar la inicialización de semáforos. - El proceso semáforo sólo puede estar rojo o verde. Cada cierto tiempo, por ejemplo 10 segundos, cambia de estado por sí mismo. - Los procesos sólo utilizarán las primitivas de semáforos, la instrucción sleep ( ) y comentarios. - Suponed que están implementados los procedimientos: bajarBarrera, subirBarrera y expenderTicket. - Un coche sólo podrá pulsar el botón de la máquina cuando la barrera está bajada. - Capacidad inicial del parking: 10 coches. Crear 15 procesos de tipo coche. TICKETS SEM.2 Suponer que estamos en una discoteca y resulta que está estropeado el servicio de chicas y todos tienen que compartir el de chicos. Se pretende establecer un protocolo de entrada al servicio usando semáforos en el que se cumplan las siguientes restricciones: - chicas sólo puede haber una a la vez en el servicio. - chicos puede haber más de uno, pero con un máximo de cinco. - los chicos tienen preferencia sobre las chicas. Esto quiere decir que si una chica está esperando y llega un chico éste puede pasar. Incluso si no puede entrar en el servicio porque hay ya 5 chicos pasará antes que la chica cuando salga algún chico. SEM.3 Una tribu de antropófagos comparte una olla en la que caben M misioneros. Cuando algún salvaje quiere comer, se sirve directamente de la olla, a no ser que ésta esté vacía. Si la olla está vacía, el salvaje despertará al cocinero y esperará a que éste haya rellenado la olla con otros M misioneros para poder coger el suyo. proceso Salvaje repetir servirse_1_misionero; comer; siempre; proceso Cocinero repetir dormir; rellenar_olla; siempre; Se pide implementar tanto el programa principal como ambos procesos en Pascal-FC usando semáforos de tal forma que se respete la sincronización requerida y se tenga en cuenta que: - la solución no debe producir interbloqueo, - los salvajes podrán comer siempre que haya comida en la olla, solamente se despertará al cocinero cuando la olla esté vacía. SEM.4 En una fábrica de bicicletas hay 2 operarios y 1 montador. El primer operario construye ruedas, el segundo operario construye marcos de bicicleta y el montador se encarga de tomar 2 ruedas y 1 marco y de esta forma montar una bicicleta. La actuación concurrente de estas 3 personas está sujeta a las siguientes restricciones: 1. El montador no podrá coger ningún material, si dicho material no ha sido fabricado de antemano por el operario correspondiente. 2. El operario que fabrica marcos no tiene espacio más que para almacenar 4 de estos objetos; deberá esperar si en cualquier momento ha fabricado 4 marcos, sin que ninguno haya sido tomado por el montador. El número máximo de objetos que puede almacenar el operario que fabrica ruedas es de 10. Solucionar el problema usando semáforos para sincronizar los 3 procesos. SEM. 5 Un conjunto de procesos tiene relaciones de precedencia si existen restricciones en el orden en el que pueden ejecutarse. Consideremos seis procesos. P1 y P2 deben ejecutarse ambos antes que P3; P3 se ejecuta antes que P4 y P5; y P6 se ejecuta despu‚s de todos los dem s. Hacer un programa que usando sem foros, permita todas estas relaciones. Permitir que las ejecuciones de los procesos sean c¡clicas, esto es, que la primera ejecuci¢n de P6 pueda ser concurrente con la segunda de P1 y P2. SEM.6 Supongamos que tenemos un área de datos compartida por una serie de procesos. El área de datos puede ser cualquier cosa: un archivo, una base de datos, etc. Hay algunos procesos que sólo pueden leer datos (lectores) y otros que sólo escriben datos (escritores). Se deben satisfacer las siguientes condiciones: - cualquier número de lectores puede leer el archivo simultáneamente - sólo puede escribir en el archivo un escritor en cada instante - si un escritor está accediendo al área de datos, ningún lector puede leerlo. Solucionar el problema usando semáforos. SEM. 7 Tenemos una peluquería con dos salas como la de la figura. En esta peluquería tenemos un barbero que afeita a sus clientes según las siguientes normas: Barbero: cuando termina con un cliente le muestra la salida. Luego comprueba la habitación de espera. Si hay clientes, lleva uno a la sala de afeitar; si no, se duerme en la sala de afeitar. Cliente: entra en la sala de espera. Si hay otros clientes, espera con ellos; si no, abre la puerta de la sala de afeitar para ver si el barbero está ocupado. Si el barbero está ocupado, cierra la puerta y espera en la sala de espera; si no lo está, entra y despierta al barbero. Se pide: programa un proceso barbero y un proceso cliente que se comporten según las normas descritas. Sala de afeitar Sala de espera SEM.8 Cinco filósofos están sentados alrededor de una mesa circular. Cada filósofo sólo tiene 2 actividades: pensar y comer. Para comer necesita dos tenedores, el que está a su derecha y el que está a su izquierda. Sólo cuando tiene los dos entonces podrá comer. Consecuentemente: - dos filósofos vecinos nunca podrán estar comiendo al mismo tiempo. - sólo 2 filósofos podrán estar comiendo al mismo tiempo. Proporcionar una solución con semáforos que permita este protocolo, evitando interbloqueos. MONITORES MON.1 Un número de procesos clientes hacen llamadas a un monitor usando el procedimiento bloquea (n), donde n es un entero entre 1 y 10. Todos los llamadores se bloquean hasta que otro proceso cliente hace una llamada al procedimiento desbloquea. Entonces los procesos bloqueados deben ser desbloqueados de uno en uno en el orden dictado por el parámetro n, es decir, primero los procesos donde n=1, luego donde n=2, etc. Cuando todos los procesos han sido desbloqueados, el proceso desbloqueador puede continuar. MON.2 Consideremos un sistema compuesto por tres procesos fumadores y un proceso agente. Cada fumador continuamente hace un cigarro y se lo fuma. Pero para poder fumarse un cigarro se necesitan tres ingredientes: papel, tabaco y cerillas. Uno de los fumadores tiene papel, el otro tabaco y el otro cerillas. El agente tiene una cantidad infinita de los tres ingredientes. El agente pone dos de los ingredientes en la mesa. El fumador que tiene el ingrediente que falta puede hacer un cigarro y fumárselo, indicando al agente cuando termine que se lo ha fumado. El agente entonces pone otros dos ingredientes y el ciclo se repite. Se pide construir un programa que sincronice convenientemente al agente y los fumadores. MON.3 Consideremos una estructura de productor/consumidor donde se tiene un buffer con una capacidad máxima de 16 enteros. El consumidor lee un entero cada vez mientras que el productor puede producir cualquier número de elementos en el rango 1..16 de una sola vez. Si no hay espacio suficiente será bloqueado. MON.4 Escribe un monitor que implemente la instrucción hardware test-and-set. Hacer también: Sem.1, Sem.2, Sem.3, Sem.6 y Sem.8 CANALES CAN.1 Escribir un programa en el que un número de procesos realizan operaciones de lectura y escritura sobre un array de enteros. El array es visible a todos los procesos, pero otro proceso u otros procesos deben regular el acceso al array de tal forma que son posibles lecturas concurrentes sobre las posiciones del array, pero la operación de escritura sobre una posición excluye otras operaciones de escritura o lectura. Nota: Un proceso lector será de la forma: Permiso[i]!any (* leer del array *) Fin[i]!any CAN.2 Construir un programa que genere los n primeros números aleatorios. La estructura de procesos será la siguiente: números filtro 1 filtro 2 ... filtro n consumidor salida donde: números es un proceso que genera una secuencia de números infinitos y se los va pasando mediante un canal al filtro 1. filtro i: va recibiendo números por el canal de la izquierda. El primero que le llega es primo y lo manda a la salida. Los siguientes números los divide por el primer número que le llegó y si la división no es exacta entonces lo manda al canal de la derecha para que sea recogido por el siguiente filtro. Si la división es entera ignora el número. salida: simplemente imprime el número que le llega por algún canal. Ese número es primo. consumidor: simplemente muestra los números que le llegan. Son candidatos a ser primos, pero no tienen por qué serlo. CAN.3 Supongamos que tenemos un cajero automático con diversos clientes. Existirán clientes de dos tipos: los que sólo tratan de sacar dinero y los que sólo tratan de ingresar dinero tal y como muestra el pseudocódigo de abajo. El cajero sólo dejará sacar dinero si la cantidad a reintegrar es menor que la cantidad de dinero de la que dispone el cajero (inicialmente 10.000 euros). Por simplicidad se supone que todos los clientes comparten la misma cuenta. La cantidad a reintegrar e ingresar por parte de los clientes es una cifra aleatoria entre 1 y 10.000 euros. Se pide implementar con canales los dos tipos de proceso cliente además del proceso cajero. Habrá 5 clientes de cada tipo. Proceso ClienteUno begin repeat ok:= puedoSacar (cantidad); if ok then writeln (‘éxito’) else writeln (‘fracaso’); until OK end; Proceso ClienteDos begin ingresar (cantidad) end; Hacer también Sem.6, Sem.8, Mon. y Can.2 INVOCACIÓN REMOTA INR.1 Consideremos una colección de n procesos. Cada uno de ellos tiene un único identificador y un valor arbitrario en el rango de 1 a 5. Comunicándose con el resto de procesos, cada proceso es capaz de encontrar cuántos de los otros procesos tienen el mismo valor. Cuidado con los deadlock que se puedan producir. INR.2 Escribir un programa en el que hay un número de procesos cliente que interactúan con un proceso cajero. Un cliente puede consultar su saldo así como sacar dinero. Sin embargo la cuenta del cliente nunca debe ser negativa. Considerad un saldo inicial para cada cliente de 50.000 ptas. INR.3 Modificar el ejercicio anterior de tal forma que ahora haya 3 cajeros disponibles que puedan trabajar simultáneamente. Un cliente puede ir a cualquier cajero. Considerad que puede haber clientes que compartan una misma cuenta. Hacer también: Sem.1, Sem.3, Sem.4 Sem.6, Sem.8, Mon. RECURSOS REC.1 Dos procesos interactúan mediante un buffer. Un proceso productor escribe 1, 2 o 3 enteros en el buffer. Si no hay sitio se bloqueará. El proceso consumidor debe bloquearse a menos que haya 7 enteros disponibles en el buffer, entonces lee los 7 enteros de una vez. Escribir un programa que simule este comportamiento. Considerar un buffer de longitud máxima 16. REC.2 Consideremos un programa que contiene dos procesos y una bolsa. La bolsa contiene un conjunto arbitrario de bolas rojas y verdes. Un proceso saca una bola de la bolsa; si es verde la tira, pero si es roja la devuelve a la bolsa. El otro proceso saca 2 bolas a la vez; si ambas son verdes, devuelve una bola a la bolsa, si ambas son rojas, las tira y devuelve una bola verde a la bolsa y si las bolas son de ambos colores se devuelve a la bolsa la roja. Implementar este programa. ¿Cuál es el estado actual de la bolsa? ¿Se podía predecir a priori? REC.3 Un método para encontrar el máximo de un conjunto de enteros es mantener el conjunto en un recurso y tener un número de procesos que hacen llamadas al recurso. Cada vez que un proceso llama, extrae dos enteros y retorna el mayor. Programar este algoritmo usando 5 procesos trabajadores. Cuando se alcance el valor final se debe escribir el valor. REC.4 Consideremos un recurso que almacena un determinado número de elementos de cualquier tipo y que proporciona dos operaciones: pedir y devolver. Pedir recibe como parámetro el número de elementos que se le piden al recurso por parte del cliente y devolver recibe como parámetro el número de elementos devueltos por el cliente. Cuando algún cliente pida más elementos de los que dispone el recurso, habrá que bloquearlo. Se desbloqueará cuando algún otro proceso cliente devuelva algún elemento.