Herramientas de Desarrollo en Informática Primitivas de sincronización (continuación) Implementación de los problemas clásicos utilizando semáforos 1.­ Productor ­ consumidor Este problema requiere sincronizar los procesos productor y consumidor. La siguiente implementación es únicamente para un productor y un consumidor: Program Prod­Cons() { /* Declaraciones e inicializaciones */ shared semaphore producidos = 0; shared semaphore libres = n; shared int in = 0; shared int out = 0; shared int buffer[n]; Procedure Productor(){ item i; for(;;){ i = produce(); wait(libres); buffer[in] = i; in = (in + 1)%n; signal (producidos); } } } Procedure Consumidor(){ item i; for (;;){ wait(producidos); i = buffer[out]; out = (out + 1)%n; signal(libres); consumir(i); } } begin ParBegin() Productor(); Consumidor(); ParEnd(); End in = out ⇒ libres = n ∨ producidos = n (el buffer está vacío ó esta lleno) Para muchos productores y un solo consumidor, el programa anterior debe modificarse agregando un nuevo semáforo ( mutex ) para controlar la exclusión mutua en al región crítica del proceso productor. El programa modificado es el siguiente: Program Prod­Cons(){ /* Declaraciones e inicializaciones */ shared semaphore producidos = 0; shared semaphore libres = n; shared semaphore mutex = 1; shared int in = 0; shared int out = 0; shared int buffer[n]; Procedure Productor(){ item i; for(;;){ i = produce(); wait(libres); wait (mutex); buffer[in] = i; in = (in + 1)%n; signal(mutex); signal (producidos); } } Procedure Consumidor(){ item i; for (;;){ wait(producidos); i = buffer[out]; out = (out + 1)%n; signal(libres); consumir(i); } } begin ParBegin() Productor(); Consumidor(); ParEnd(); } End Asignaciones: ­ Realizar la solución del problema para más de un productor y más de un consumidor. 2.­ Lectores ­ escritores 2.1 ­ Con prioridad a los lectores /* variables e inicializaciones */ semaphore w = 1; /* número de escritores */ semaphore lmutex = 1; int ar = 0; /* número de lectores activos */ Lectores(){ wait (lmutex); ar = ar + 1; if ar = 1 then /* Si es el primer lector */ wait (w); signal(lmutex); Realizar Lectura; wait(lmutex); ar = ar ­ 1; if (ar = 0) then /* Si es el último lector. Esto es para signal (w); evitar signals innecesarios */ signal (lmutex); } Escritores(){ wait(w); Realizar Escritura; signal(w); } 2.2 ­ Con prioridad a los escritores /* variables e inicialización */ semaphore r = 0; semaphore w = 0; semaphore wmutex = 1; semaphore lmutex = 1; int ar = 0; /* número de lectores activos */ int rr = 0; /* número de procesos que están "leyendo" */ int aw = 0; /* número de escritores activos */ int ww = 0; /* número de procesos "escribiendo". Esta variable es binaria ya que sólo puede haber un proceso escribiendo a la vez */ Lectores(){ wait(lmutex); ar = ar + 1; if aw = 0 then { rr = rr + 1; signal (r); } signal(lmutex); } wait (r); Realizar Lectura; wait(lmutex); rr = rr ­ 1; ar = ar ­ 1; if rr = 0 then while ww < aw { ww = ww + 1; signal(w); } signal (lmutex); Escritores(){ wait(lmutex); aw = aw + 1; if rr = 0 then { ww = ww + 1; signal(w); } signal(lmutex); wait (w); wait (wmutex); Realizar Escritura; signal(wmutex); wait(lmutex); aw = aw ­ 1; ww = ww ­ 1; if aw = 0 then while rr < ar { rr = rr + 1; signal (r); } signal(lmutex); } En esta implementación los lectores y escritores entran según estén encolados . 3.­ Barbero dormilón /* Inicialización de los semáforos */ semaphore clientes = 0; /* Número de clientes en espera del servicio */ semaphore barbero = 0; /* Los clientes esperan por este semáforo */ semaphore mutex = 1; /* variables */ int esperando = 0; /* número de clientes en espera. Esta variable es una copia del semáforo clientes que se utiliza para verificar si hay o no sillas vacías */ Barbero() { while(true) { wait (clientes); /* Duerme si no hay clientes */ wait (mutex); esperando ­­; signal(barbero); /* Está listo para cortar el cabello */ signal(mutex); cut_hair(); } } Clientes(){ wait(mutex); if (esperando < NUM_SILLAS) then /* Se va si no hay sillas { desocupadas */ esperando ++; signal(clientes); /* Despierta al barbero si es necesario */ signal(mutex); wait(barbero); /* Duerme si el barbero está ocupado */ get_hair_cut(); } else signal(mutex); } Asignación: Realizar el problema para muchos barberos y muchos clientes. 4.­ Cena de los filósofos /* Semáforos */ chopstick array[0 .. 4] of Sem = {1,1,1,1} Filósofo() { loop { Pensar; wait (chopstick[(i+1)%5]); wait (chopstick[(i­1)%5]); Comer; signal(chopstick[(i+1)%5]); signal(chopstick[(i­1)%5]); } }