PROGRAMACIÓN CONCURRENTE Tema 5 Monitores 1
Indice Definición de los monitores Sincronización condicional usando monitores Algunos problemas con monitores 2
Problemas de las regiones críticas condicionales Pueden estar dispersas en el texto del programa. La integridad de la estructura de datos compartida es facilmente dañada debido a que no hay control sobre que operaciones son realizadas por el programador dentro de una region crítica. Dificiles de implementar eficientemente. 3
Definición de los monitores Las regiones críticas se escriben como funciones y se encapsulan juntas en un módulo único llamado monitor. 4
Definición de los monitores Un monitor es un mecanismo que permite compartir de una manera fiable y efectiva tipos abstractos de datos entre procesos concurrentes. Asi pues un monitor proporciona: Abastracción de datos Exclusión mutua y mecanismos de sincronización entre procesos. Un monitor es similar a un TAD en el sentido de que esconde la represnetación interna de sus variables y proporciona al exterior sólo el comportamiento funcional definido por las operaciones exportadas. 5
Definición de los monitores Un procedimiento exportado se puede invocar desde fuera del monitor: identificador_monitor.identificador_procedimiento(parametros_actuales); El compilador garantiza que el acceso al código dentro de un monitor se realiza bajo exclusión mutua. Un proceso que intenta ejecutar un procedimiento del monitor cuando hay otro proceso ejecutando uno de los procedimientos en el mismo monitor se bloquea en la cola del monitor Cuando un proceso finaliza su llamada a procedimiento de monitor, la exclusión mutua se pasa a uno de los procesos bloqueados. 6
Sincronización condicional usando monitores La sincronización condicional se proporciona mediante variables etiquetadas como condition. Son colas FIFO (inicializadas automáticamente a la cola vacía en la declaración) que no tiene valores accesibles para el programador. Se declaran: var C: condition; Se declaran dentro de un monitor y se usan para bloquear y desbloquear procesos. 7
Sincronización condicional usando monitores Se definen dos operaciones (procedimientos) sobre una variable condition (C): delay(c) resume(c) delay(c) libera el monitor y bloquea el proceso invocador en C. resume(c) desbloquea el primer proceso esperando en C. La función empty retorna un valor booleano que determina si la cola está vacía. 8
Problema: Productor-Consumidor Buffer Limitado (1) monitor Buffer; const TamañoBuffer = 5; MaxIndBuffer = 4; var Almacen : array[0..maxindbuffer] of char; NumChar: integer; NoLleno, NoVacio : condition; ProxEn, ProxSal: integer; procedure Insertar(ch: char); if NumChar >= TamañoBuffer then delay(nolleno); Almacen[ProxEn] := ch; NumChar := NumChar +1; ProxEn := (ProxEn +1) mod TamañoBuffer; resume(novacio); procedure Sacar(var ch: char); if NumChar = 0 then delay(novacio); ch := Almacen[ProxSal]; NumChar := NumChar -1; ProxSal := (ProxSal +1) mod TamañoBuffer; resume(nolleno); NumChar := 0; ProxEn := 0; ProxSal := 0; 9
Problema: Productor-Consumidor Buffer Limitado (2) process Productor; var local : char; for local := a to z do Buffer.Insertar(local); process Consumidor; var ch: char; repeat Buffer.Sacar(ch); write(ch); until ch = z ; writeln program pcmon; (*Definición del monitor*) (*Proceso productor*) (*Proceso consumidor*) co Productor; Consumidor; coend 10
Problema: Lectores Escritores (1) process type Lector; repeat LeerEscribir.Entrada(true); (*Acceder a los datos*) LeerEscribir.Salida(true); (*Usar la información*) forever process type Escritor; repeat (* Producir nueva información *) LeerEscribir.Entrada(false); (*Modificar los datos*) LeerEscribir.Salida(false); forever 11
Problema: Lectores Escritores (2) monitor LeerEscribir; var ContadorLect: integer; EscritorActivo: boolean; OKLeer, OKEscribir: condition; procedure Entrada(Leyendo: boolean); if Leyendo then if EscritorActivo or not empty(okescribir) then delay(okleer); ContadorLect := ContadorLect +1; resume(okleer); end else if EscritorActivo or (ContadorLectores <> 0) then delay(okescribir); EscritorActivo := true; end procedure Salida(Leyendo: boolean); if Leyendo then ContadorLect := ContadorLect -1; if ContadorLect = 0 then resume(okescribir); end else EscritorActivo := false; if not empty(okleer) then resume(okleer) else resume(okescribir) end EscritorActivo := false; ContadorLect := 0; 12