Definición Semáforos Definición Semáforos Tipo abstracto de datos (Dijkstra) Especificación de comportamiento: Lecturas: Ben-Ari, secciones 4.1, 4.2, 4.3, 4.6 Andrews, intro. cap. 4 y sección 4.1 sem ∈ N Init(sem, n) Wait(sem) Signal(sem) ≡ h sem := n i ≡ h AWAIT sem > 0 → sem := sem - 1 i ≡ h sem := sem + 1 i Código entre h· · · i: acción atómica Manuel Carro Init(sem, n): sólo inicialización valores Universidad Politécnica de Madrid AWAIT Cond suspende tarea hasta cumplimiento de Cond Wait(sem): suspende hasta que sem > 0, entonces decrementa Signal(sem): incrementa sem Este texto se distribuye bajo los términos de la Creative Commons License M. Carro (UPM) Semáforos 1 / 20 M. Carro (UPM) Definición Semáforos 2 / 20 Definición Exclusión mutua con semáforos Semáforos Clases e implementación X := ...; −−Compartida Init (Mutex , 1); −−Nadie en sección crı́tica Wait ( Mutex ) ; X := X + X; −− S .C . S i g n a l ( Mutex ) ; Binarios (sem ∈ {0, 1}): exclusión mutua Invariante: Mutex = 0 ↔ algún proceso en sección crı́tica Generales (sem ∈ N ): sincronización más avanzada Semáforos binarios: Signal cuando ya tiene un valor 1 → efecto indefinido No son parte nativa de Ada Implementación (entre los ejemplos de la asignatura) como packages: Bin Semaphore : binario Semaphore : generales Wait: Puede decrementar si sección crı́tica está libre Suspende en otro caso Definen tipo paramétrico (para inicializar semáforo) Signal: Siempre puede incrementar Puede rearrancar alguna tarea suspendida M. Carro (UPM) Semáforos 3 / 20 M. Carro (UPM) Semáforos 4 / 20 Un interfaz de semáforos Un interfaz de semáforos Semáforos en Ada Semáforos en Ada Cuestiones sintácticas Sólo diferencias sintácticas con el esquema ya visto: Inicialización explı́cita en declaración de variable: X : Natural : = 1 ; −− V a r i a b l e compartida Mutex: Bin Semaphore.Semaphore Type(1); Notación de objetos: −− Sem áforo b i n a r i o i n i c i a l i z a d o a 1 Mutex : Bin Semaphore . Semaphore Type ( 1 ) ; task type Add ; task body Add i s begin Mutex . Wait ; −− Entrada en s e c c i ó n c r ı́ t i c a X := X + X; −− Secci ón c r ı́ t i c a Mutex . S i g n a l ; −− S a l i d a de s e c c i ó n c r ı́ t i c a end Add ; M. Carro (UPM) Semáforos Usando semáforos 5 / 20 Procedimientos Objetos Wait(Mutex) Mutex.Wait Signal(Mutex) Mutex.Signal M. Carro (UPM) Control de aparcamiento Semáforos Usando semáforos Semáforos generales: sincronización 6 / 20 Control de aparcamiento Operaciones externas, procesos, recursos Binarios: exclusión mutua (ya sabı́amos hacerla) Aparcamiento Generales: misma definición (excepto que sem ∈ N ), más potencia Barrera_Entrada Ejemplo: aparcamiento 1 entrada / 1 salida Proceso Entrada Abrir_Entrada Barrera_Salida Entrar Salir Estado Aparcamiento Proceso Salida Abrir_Salida procedure Barrera Entrada: detecta coche a la entrada; bloqueante procedure Abrir Entrada: abre la barrera de entrada procedure Barrera Salida: detecta coche a la salida; bloqueante Barreras / detectores de entrada y salida procedure Abrir Salida: abre barrera saluda Permitir entrar coches (si hay sitio) Estado Aparcamiento: depende de la implementación Descontar los que vayan saliendo M. Carro (UPM) Semáforos 7 / 20 M. Carro (UPM) Semáforos 8 / 20 Usando semáforos Control de aparcamiento Usando semáforos Aparcamiento: solución 0 Control de aparcamiento Aparcamiento: solución 1 Con un semáforo binario loop −− Entrada Espacio : = False ; Barrera Entrada ; while not Espacio loop i f N C < Max then N C := N C + 1; Espacio : = True ; end i f ; end loop ; Abrir Entrada ; end loop ; N C : Tipo Tam : = 0 ; loop −− S a l i d a Barrera Salida ; N C : = N C − 1; Abrir Salida ; end loop ; M. Carro (UPM) Semáforos Usando semáforos Solución 1: protección de 9 / 20 M. Carro (UPM) ¿Llevar mutex fuera de bucle principal? ¿Encapsular sólo N C := N C + 1? ¿No encapsular Espacio := True? Semáforos 10 / 20 Control de aparcamiento Solución 2 while not Espacio loop Mutex . Wait ; i f N C < Max then N C := N C + 1; Espacio : = True ; end i f ; Mutex . S i g n a l ; end loop ; −− Hay espacio Pero: aparcamiento lleno −→ espera activa Semáforos Usando semáforos NC Acceso en exclusión mutua M. Carro (UPM) loop −− Tarea s a l i d a Barrera Salida ; Mutex . Wait ; N C : = N C − 1; Mutex . S i g n a l ; Abrir Salida ; end loop ; Control de aparcamiento Recurso compartido: número coches aparcados loop −− Tarea e n t r a d a Barrera Entrada ; Espacio : = False ; while not Espacio loop Mutex . Wait ; i f N C < Max then N C := N C + 1; Espacio : = True ; end i f ; Mutex . S i g n a l ; end loop ; AbrirE ; end loop ; Mutex : Semaphore Type ( 1 ) ; N C : Tipo Tam : = 0 ; 11 / 20 Mutex , No Lleno : Semaphore Type ( 1 ) ; N C : Tipo Tam : = 0 ; loop −− S a l i d a Barrera Salida ; Mutex . Wait ; N C : = N C − 1; i f N C = MAX − 1 then No Lleno . S i g n a l ; end i f ; Mutex . S i g n a l ; Abrir Salida ; end loop ; M. Carro (UPM) loop −− Entrada Barrera Entrada ; No Lleno . Wait ; Mutex . Wait ; N C := N C + 1; i f N C < Max then No Lleno . S i g n a l ; end i f ; Mutex . S i g n a l ; Abrir Entrada ; end loop ; Semáforos 12 / 20 Usando semáforos Control de aparcamiento Usando semáforos Solución 2: fuego cruzado Control de aparcamiento Solución 3 Mutex: protege sección crı́tica Huecos : Semaphore . Semaphore Type ( Max ) ; No Lleno: sincroniza (sincronización condicional) No Lleno = 0 ←→ N C = MAX loop −− S a l i d a Barrera Salida ; Huecos . S i g n a l ; Abrir Salida ; end loop ; (−→ bloqueo si aparcamiento lleno) No Lleno = 0 sii ha entrado el último coche No obvio — pero no hace espera activa ¿Intercambiar No Lleno.Wait y Mutex.Wait? loop −− Entrada Barrera Entrada ; Huecos . Wait ; Abrir Entrada ; end loop ; Huecos.Wait permite paso si hay espacio Huecos.Signal libera espacio ¿El poder de los semáforos? Codificar con Peterson Repetir análisis suponiendo que hay dos (o más) entradas M. Carro (UPM) Semáforos Usando semáforos 13 / 20 M. Carro (UPM) Buffer acotado Semáforos Usando semáforos Buffer acotado Mutex : Bin Semaphore ( 1 ) ; Buffer : Tipo Buffer ; Solución 1: sólo exclusión mutua Buffer acotado 14 / 20 Cola acotada Procesos leen y escriben Productor Consumidor Buffer lleno: productor espera Buffer vacı́o: consumidor espera Buffer Proceso Productor Poner(Item) Tomar(Item) loop P r o d u c i r ( Un Dato ) ; Mutex . Wait ; << I n s e r t a en b u f f e r >> Mutex . S i g n a l ; end loop ; Proceso Consumidor Precondiciones secuenciales vs. Precondiciones concurrencia Estado Buffer M. Carro (UPM) Semáforos loop Mutex . Wait ; << Q u i t a de b u f f e r >> Mutex . S i g n a l ; U t i l i z a r ( Un Dato ) ; end loop ; 15 / 20 M. Carro (UPM) Semáforos 16 / 20 Usando semáforos Buffer acotado Usando semáforos Solucion 2 Mutex : Buffer : Vacios : Llenos : Buffer acotado Buffer de un dato Semáforos con dos misiones diferentes Bin Semaphore ( 1 ) ; Tipo Buffer ; Semaphore ( Max ) ; Semaphore ( 0 ) ; Esencialmente, aparcamiento simétrico M. Carro (UPM) loop −− P r o d u c t o r P r o d u c i r ( Un Dato ) ; Vacio . Wait ; Dato : = Un Dato ; Lleno . S i g n a l ; end loop ; Pero: estructura de datos separada de semáforo loop −− P r o d u c t o r P r o d u c i r ( Un Dato ) ; Vacios . Wait ; Mutex . Wait ; <<I n s e r t a en b u f f e r >> Mutex . S i g n a l ; Llenos . S i g n a l ; end loop ; loop −− Consumidor Llenos . Wait Mutex . Wait ; <<Q u i t a de b u f f e r >> Mutex . S i g n a l ; Vacios . S i g n a l Consumir ( Un Dato ) ; end loop ; Semáforos Dato : Tipo Dato ; Lleno : Bin Semaphore ( 0 ) ; Vacio : Bin Semaphore ( 1 ) ; loop −− Consumidor Lleno . Wait Este Dato : = Dato ; Vacio . S i g n a l ; Consumir ( Este Dato ) ; end loop ; Establecer invariantes ¿Por qué es más simple que el buffer general? 17 / 20 M. Carro (UPM) Ventajas e inconvenientes Semáforos 18 / 20 Ventajas e inconvenientes Semáforos desde la lejanı́a Ejercicio: buffer par/impar Algo truculentos y de bajo nivel Productor de números pares e impares (en cualquier orden) Consumidores: Pero ampliamente disponibles (POSIX, API Win32) Sincronización condicional ad-hoc I I Linealización siempre posible, pero a veces no clara Uno necesita números pares Otro necesita números impares Mezclada con exclusión mutua Para implementar abstracciones de nivel superior Buffer Proceso Productor Consumidor Pares Tomar_Par(Item) Poner(Item) Tomar_Impar(Item) Estado Buffer Consumidor Impares Usar un buffer de un dato M. Carro (UPM) Semáforos 19 / 20 M. Carro (UPM) Semáforos 20 / 20