Tema 3 - Departamento de Lenguajes y Sistemas Informáticos

Anuncio
Tema 3. Monitores
Programación Concurrente
Depto. de Lenguajes y Sistemas Informáticos
Universidad de Granada
Contenidos
1. Concepto de Monitor
1.1. Fundamento teórico de los monitores
1.2. Sintaxis de los monitores
1.3. Exclusión mutua con monitores
1.4. Instanciación de monitores
2. Sincronización en Monitores
2.1. Primitivas de sincronización en monitores
2.2. Efecto de las operaciones sincronización sobre la exclusión
mutua del monitor
2.3. Equivalencia entre semáforos y monitores
2.4. Problemas paradigmáticos resueltos con monitores
1. Concepto de Monitor
1.1. Fundamento teórico de los monitores
•
Inconvenientes mecanismos como los semáforos:
•
Monitor (Hoare 1974) : Mecanismo de alto nivel que permite
•
Monitor = Encapsulación
– Basados en variables globales → No modular.
– Uso y función de las variables no explícito.
– Operaciones sobre variables recurso dispersas y no protegidas.
• No Acceso estructurado ni encapsulación → Fuente de errores.
– Definir objetos abstractos compartidos (una colección de datos y procedimientos
asociados que se comparten por varios procesos).
– Garantizar acceso exclusivo a datos e implementar sincronización.
– Definición recurso (datos).
– Operaciones de Manipulación (procedims.)
•
Recurso: Se percibe como un módulo al que se accede concurrentemente.
– El usuario ignora detalles de implementación del recurso y de las
operaciones asociadas.
1. Concepto de Monitor
1.1.1. Centralización de funciones críticas.
•
•
•
•
•
•
Origen: S.O. concurrente → Monitor monolítico → Programa que centraliza las
funciones críticas (asig./planif. recursos) del sistema.
Soportados por facilidades hardware:
– Ejecución en modo ininterrumpido (E.M.).
– Acceso a posiciones de memoria privilegiadas.
– Ejecución de instrucciones privilegiadas.
Monitor: Versión “descentralizada” del monitor original.
Cada monitor tiene:
– Una función específica.
– Datos e instrucciones propias.
Ejemplo:
– M1 : único monitor que accede a v1 → asegura E.M. ya que será
ininterrumpible (la entrada al monitor de un proceso excluye la entrada de
otros).
– Único procesamiento sobre v1 programado en M1.
Diferentes monitores (o instancias de un monitor) para diferentes tareas.
– Mayor Eficiencia (+ Concurrencia)
– Mayor Robustez: Modularidad
1. Concepto de Monitor
1.1.2. Estructuración en el acceso a los datos.
• Definición tipos para las operaciones y los datos (T.A.D.).
• Paradigma de Programación Modular:
– Módulo: Conjunto de procedimientos relacionados + datos.
– Principio de Ocultación de datos: Hacer local al módulo todo lo
que no debe ser visible.
• Ejemplo: Módulo de pila. Resolver:
– Interfaz de usuario: procedimientos push y pop.
– Representación (p.e. array) sólo accedida mediante interfaz.
– Inicialización antes de uso.
• Lenguajes de Programación Dirigida a Objetos→ Clase.
1. Concepto de Monitor
1.2. Sintaxis de los monitores
Estructura de un monitor de nombrename y procedimientos
op1,...,opN:
Monitor name;
var
... Declaración de variables permanentes
procedure op1 (...);
var
... Declaración de variables locales a op1
{ ... Código que implementa op1 }
... ... ...
procedure opN (...);
var
... Declaración de variables locales a opN
{ ... Código que implementa opN }
begin
... Código para inicializar variables permanentes
end.
1. Concepto de Monitor
1.2.1. Protección de los datos en el monitor.
• Ámbito variables permanentes del monitor : Código monitor
(procedimientos y cod. inicialización).
• Acceso variables permanentes: sólo dentro de los
procedimientos.
• Procedimientos sólo acceden:
– Variables permanentes
– Variables locales
• Valores variables permanentes se mantienen entre diferentes
ejecuciones de los procedimientos.
• Comunicación monitor-mundo exterior: A través de los
parámetros de los procedimientos.
1. Concepto de Monitor
1.2.2. Procedimientos del Monitor.
• Comunes a todos los procesos del sistema.
• Nueva llamada proced. → Nuevos valores parámetros y
variables locales.
• Sintaxis:
nombremonitor.nombreprocedimiento(parámetros_reales);
1.2.3. Código de inicialización
• Ejecución sólo 1 vez: Inicializa vars. Permanentes.
• Tras Ejecución: Monitor = objeto pasivo (datos + proceds.)
• Única forma ejecutar monitor: llamar proced.
1. Concepto de Monitor
1.3. Exclusión mútua con monitores
•
Acceso al monitor en E.M.
– Sólo un proceso en un momento dado puede ejecutar un procedimiento
• Subsiguientes llamadas esperan finalización.
– Violación podría tener efectos caóticos sobre vars.
•
Ventajas sobre Semáforos (soluc. no estructurada):
– Protección Variables: evita interferencias exteriores
– Estructuración acceso: Espera y señalización se programan dentro monitor. Si
el monitor es correcto, lo será cada instancia utilizada por los procesos.
– E.M. garantizada automáticamente → No errores.
•
Invariante: Define una relación sobre los datos del monitor.
– Se mantiene siempre excepto cuando un procedimiento está ejecutándose.
– Se ha de cumplir antes de entrar y después de salir.
– Se ha de reestablecer el invariante en procedimientos antes de devolver el
control o suspender el proceso.
1. Concepto de Monitor
1.4. Instanciación de monitores
• Permite declarar diversos monitores con estructura y
comportamiento idénticos (Ej.: planificar varios recursos
similares).
• Declaración tipo monitor:
Class Monitor nombre_clase
.... .......
• Instanciación de monitores: monitor1, monitor2: nombreclase;
• Práctica: se permite declarar varias instancias e incluso
conjuntos parametrizados de monitores.
• Implementación con procedimientos reentrantes:
– Basta asignar nuevas instancias de las variables globales
para cada instancia de un monitor.
2. Sincronización en Monitores
2.1. Primitivas de sincronización en monitores
• Sincronización: Facilidad de bloqueo-activación de acuerdo
a una condición.
• Propósitos de las instrucciones de sincronización en
semáforos:
– Bloqueo-activación
– Cuenta (representación condición)
• En monitores:
– Sólo Bloqueo-activación
– Representación condición mediante datos protegidos del
monitor
2. Sincronización en Monitores
2.1. Primitivas de sincronización en monitores (cont.)
• Ejemplo de monitor: Planificador de un único recurso (sem. binario)
monitor recurso;
var ocupado: boolean;
noocupado: condicion;
procedure adquirir;
{if ocupado then noocupado.wait; ocupado := true}
procedure liberar;
{ocupado := false; noocupado.signal;}
begin
ocupado := false /* valor inicial*/
end;
2. Sincronización en Monitores
2.1.1. Semántica de las operaciones
●
●
Wait: "estoy esperando a que algo (condición) ocurra".
– Bloquea proceso.
Signal: "estoy señalando que algo (condición) ha ocurrido".
– Reactiva un proceso bloqueado en esa condición.
• Responsabilidad del programador→ que el proceso ejecute:
– Wait: cuando algo (condición) no se dé
– Signal: Cuando la condición acabe de activarse.
2. Sincronización en Monitores
2.1.2. Variables de condición o señales
• Más de una razón para esperar:
– representan distintas condiciones
– Deben de ser diferenciadas por wait y signal.
• Nuevo tipo de variable:
– Variable de condición o señal. Sin valor almacenado (ni V, ni F).
– Una variable condición por cada razón de bloqueo.
• Operaciones
Nombre_variable_condición.wait
Nombre_variable_condición.signal
• Representación variable condición
– Cola (inicialmente vacía) de procs esperando en condición. Invisible
a procs.
• Más de un proceso puede estar dentro del mismo monitor, aunque sólo
uno ejecutándose (resto bloqueados en variables condición).
2. Sincronización en Monitores
2.1.3. Propiedad FIFO de las colas de condición
• Más de un proc. esperando en condición →
– condición.signal reactivará el proc. que lleve más tiempo
esperando.
• Cada proc. en cola obtendrá eventualmente su turno→ No
inanición.
●
condición.queue
– Función booleana = V → Hay algún proc. esperando en
condición.
2. Sincronización en Monitores
2.1.4. Colas de condición con prioridad
• Propiedad FIFO: evita inanición.
• Mayor control sobre estrategia de planificación: prioridad del proceso
en espera como nuevo parámetro.
Nombre_var_condición.wait (prioridad:integer);
• Formato:
• Signal reanuda proceso que especificó el valor más bajo de prioridad.
• Precaución diseño monitor: Evitar riesgos como la inanición.
• Justificación:
– Ningún efecto sobre la lógica del programa: Funcionamiento
similar con/sin colas de prioridad. Sólo mejora características dep.
del tiempo.
– Ordenación automática cola: técnica de planificación rápida y
sencilla, excepto si la cola es muy larga.
– Almacenamiento requerido por proceso: una palabra
2. Sincronización en Monitores
2.1.4. Colas de condición con prioridad (cont.)
Ejemplo: Reloj con alarma. El proc. llamador se retardan unidades de
tiempo.
monitor despertador;
var ahora: integer; despertar: condicion;
procedure despiertame (n: integer);
var alarma: integer;
{alarma := ahora + n; while ahora<alarma do despertar.wait (alarma);
despertar.signal; /* Por si otro proceso coincide en la alarma */ }
procedure tick;
{ahora := ahora + 1; despertar.signal;}
begin
ahora := 0;
end;
2. Sincronización en Monitores
2.1.4. Colas de condición con prioridad (cont.)
Ejemplo: Asignación recurso "siguiente trabajo el más corto".
monitor asignador;
var
libre: boolean; turno: condicion;
procedure petición (tiempo: integer);
{if not libre then turno.wait (tiempo); libre:=false;}
procedure liberar;
{libre := true; turno.signal;}
begin
libre:= true;
end;
2. Sincronización en Monitores
2.2. Efecto de las operaciones de sincr. sobre la E.M. del monitor
•
Requisito de reanudación inmediata
•
Única forma de garantizar que procesos en espera puedan adquirir un recurso que
acaba de ser liberado → Evita inanición.
•
Propuesta de Hoare
•
Propuesta de Brinch-Hansen
– Un Signal deberá ir seguida inmediatamente por la reanudación de un proceso en espera,
sin que exista la posibilidad de que intervenga la llamada a un procedimiento de un tercer
proceso.
– Un proceso suspendido debido a ejecución de signal, entrará en una cola de suspendidos
en Signal. Cada proceso antes de salir del monitor y liberar la E.M., comprueba si hay
procesos en esta cola, si los hay, heredarán la E.M. Los procesos suspendidos al ejecutar
una operación signal tienen prioridad sobre los que intentan entrar.
– Signal sólo como última instrucción del cuerpo.
– Evita cola de suspendidos en signal → + Eficiencia
2. Sincronización en Monitores
2.2.1. Problema de Anidación de llamadas en monitores
• Sistema estructurado como colección jerárquica de monitores:
procs. de un monitor pueden llamar a otro
• Problema:
– Una llamada de monitor anidada se suspende en el último monitor. La
E.M. en el último se abandonará pero no en el monitor desde el que
se llama.
– Los procesos que intenten llamar a procedimientos de cualquier
monitor de la cadena se bloquearán.
– Menor concurrencia → Menor rendimiento.
2. Sincronización en Monitores
2.2.1.1. Problema de Anidación. Propuestas de solución
a) Prohibir llamadas anidadas.
b) Liberar exclusión mútua en todos los monitores implicados en la cadena y bloquear
proceso.
–
–
Una vez señalado, el proceso necesitará readquirir el acceso exclusivo a todos los
monitores.
Requerirá que el invariante del monitor se establezca antes de cualquier llamada que
pueda bloquear.
c) Monitores = herramienta de estructuración para recursos compartidos. E.M. →
sólo forma de preservar integridad del recurso.
–
–
Hay casos en los cuales las operaciones de un monitor pueden ejecutarse
concurrentemente sin efectos adversos.
Definir construcción que permita especificar que ciertas operaciones se podrán ejecutar
concurrentemente y la exclusión mútua se liberará.
2. Sincronización en Monitores
2.3. Equivalencia entre semáforos y monitores
• Los monitores pueden ser implementados por semáforos.
• Garantizar la E.M.de los cuerpos los procedimientos
– Para cada monitor → Semáforo binario mutex (inic. a 1) para asegurar
exclusión mútua entre los cuerpos de procedimientos.
• mutex:bin_sem=1
• ENTRADA Proc. → P(mutex)
• SALIDA
Proc. → Normalmente V(mutex)
2. Sincronización en Monitores
2.3. Equivalencia entre semáforos y monitores (cont.)
Propuesta de Hoare:
– Semáforo urgente (inic. a 0) para cola de bloqueados en Signal
– Contador procs. esperando en urgente (conturgente, inic. a 0).
• Procesos que invocan un signal ejecutan:
if (existen procs. bloqueados en wait) {conturgente ++;
P(urgente) }
• Para liberar procs. bloqueados en signal, antes de liberar la
exclusión mútua, cada proceso ejecuta:
if conturgente>0 V(urgente)
else V(mutex);
2. Sincronización en Monitores
2.3. Equivalencia entre semáforos y monitores (cont.)
• Para cada variable condición del monitor:
– Semáforo semcondición (inic. a 0) para cola de bloqueados en Wait
– Contador de nº procs. esperando condición (contcondición inic. a 0).
condición.signal
conturgente + +;
if contcondición>0
{ V(semcondición);
P(urgente); }
conturgente - - ;
condición.wait
contcondición + +;
if conturgente>0
V(urgente)
else V(mutex);
P(semcondición);
contcondición - -;
2. Sincronización en Monitores
2.3.1. Equivalencia entre semáforos y monitores. Mejoras
• Salida del cuerpo de un procedimiento sin wait ni signal
V(mutex)
– conturgente no ha cambiado.
• Salida cuando signal es la última instrucción del cuerpo:
if contcondición > 0
V(semcondición)
(*) else if conturgente>0 V(urgente)
else V(mutex);
• No hay otro wait o signal en el cuerpo (*) puede omitirse.
• Propuesta de Brinch-Hansen
– signal última operación del cuerpo conturgente y urgente se omiten
– Esta simplificación sugiere que todas las operaciones signal deberían siempre
ser la última operación de un proc. del monitor.
2. Sincronización en Monitores
2.3.2. Semáforos v.s. Monitores
• Equivalentes en potencia expresiva.
• Motivación de uso Monitores: Claridad y fiabilidad.
• Característica que no se puede implementar en semáforos:
Suposición FIFO sobre la cola.
2. Sincronización en Monitores
2.4. Problemas paradigmáticos resueltos con monitores
2.4.1. Productor/consumidor utilizando un buffer circular
program productorconsumidor;
monitor buffercircular;
CONST tamaño=...;
VAR b:array [0..tamaño-1] of integer; in, out, n: integer; novacio, nolleno:
condicion;
procedure añadir (v:integer);
{if (n==tamaño) nolleno.wait;
/* Espera a que no esté lleno*/
b[in] = v; in = (in + 1) % tamaño; n ++; novacio.signal;}
procedure tomar(var v:integer);
{if (n==0) novacio.wait;
/* Espera a que no esté vacío */
v = b[out]; out = (out + 1) % tamaño; n --; nolleno.signal;}
{in = out = n = 0}
2. Sincronización en Monitores
2.4.1. Productor/consumidor utilizando un buffer circular (cont.)
procedure productor;
VAR v: integer;
{while (true) {producir(v);añadir(v)}
procedure consumidor;
VAR v:integer;
{while (true) {tomar(v);consumir(v) }
{
cobegin
/* programa principal*/
productor; consumidor;
coend; }
2. Sincronización en Monitores
2.4.2.Problema de los lectores/escritores sin prioridades (FIFO).
program lectoresescritores;
monitor leerescribir;
VAR lectores: integer; escribiendo: boolean; okleer, okescribir: condicion;
procedure comenzarleer;
{if (escribiendo or okescribir.queue) okleer.wait;
lectores + +; okleer.signal}
procedure finleer; {lectores - -; if (lectores==0) okescribir.signal;}
procedure comenzarescribir;
{if (lectores!=0 or escribiendo) okescribir.wait;
escribiendo= true }
procedure finescribir;
{escribiendo = false; if (okleer.queue) okleer.signal else okescribir.signal }
{lectores =0;
escribiendo = false}
2. Sincronización en Monitores
2.4.2.Problema de los lectores/escritores sin prioridades (FIFO).cont.
procedure procesolector;
{ while (true) {comenzarleer; leerdatos; fin leer;}
procedure procesoescritor;
{ while (true) { comenzarescribir; escribirdatos; finescribir }
{cobegin
procesolector; procesolector; ...
procesoescritor; procesoescritor; ...
coend; }
2. Sincronización en Monitores
2.4.3. Implementación con semáforos del productor/consumidor
• Propuesta de Brinch Hansen(/*signal es la última instrucción*/
program productorconsumidor;
CONST tamaño=...;
VAR b: array [0..tamaño-1] of integer; in, out, n: integer;
s: semaphore; /para E.M.*/
semnovacio, semnolleno: semaphore; /* binarios */
contnovacio, contnolleno: integer;
procedure añadir (v:integer);
{ P(s); if (n==tamaño) { contnovacio+ +; V(s); P(semnovacio); contnovacio --}
b[in] = v; in := (in + 1) % tamaño; n + +;
if contnolleno>0 V(semnolleno)
else V(s);}
procedure tomar(var v:integer);
{ P(s); if (n==0) {contnolleno + +; V(s); P(semnolleno); contnolleno - -}
v := b[out]; out := (out + 1) % tamaño; n := -- ;
if contnovacio>0 V(semnovacio) else V(s); }
2. Sincronización en Monitores
2.4.3. Implementación con semáforos del productor/consumidor
procedure productor;
var v: integer;
{while (true) {producir(v); añadir(v)}
procedure consumidor;
var
v:integer;
{while (true) {tomar(v); consumir(v)}
{in =out=n = 0; s = 1;
contnolleno = semnolleno = 0;
contnovacio = semnovacio = 0;
cobegin
productor;
consumidor;
coend;}
Descargar