Download monitores en java

Document related concepts
no text concepts found
Transcript
MONITORES EN JAVA
Ø
Ø
Ø
Ø
Un monitor es un objeto que implementa acceso bajo e.m.
a todos sus métodos, y provee sincronización
En Java, son objetos de una clase cuyos métodos públicos
son todos synchronized
Un objeto con métodos synchronized proporciona un
cerrojo único que permite implantar monitores con
comodidad y e.m. bajo control
Los métodos wait(), notify(), notifyAll()
permiten sincronizar los accesos al monitor, de acuerdo a la
semántica de los mismos ya conocida.
© Antonio Tomeu
Control de la Concurrencia en Java:
1 API Estándar
ESTUCTURA SINTÁCTICA DE UN MONITOR EN JAVA
class Monitor {
//definir aquí datos protegidos por el monitor
public Monitor(){…} //constructor
public synchronized tipo1 metodo1()
throws InterruptedException{
…
notifyAll();
…
while(!condicion1) wait();
}
public synchronized tipo2 metodo2()
throws InterruptedException{
…
notifyAll();
…
while(!condicion1) wait();
}
}© Antonio Tomeu
Control de la Concurrencia en Java:
2 API Estándar
SEMÁNTICA DEL MONITOR EN JAVA
Ø
Ø
Ø
Cuando un método synchronized del monitor
llama a wait() libera la e.m. sobre el monitor y
encola al hilo que llamó al método en el wait-set.
Cuando otro método del monitor hace notify(),
un hilo del wait-set (Java no especifica cuál)
pasará a la cola de hilos que esperan el cerrojo y se
reanudará cuando sea planificado.
Cuando otro método del monitor hace
notifyAll(), todos los hilos del wait-set
pasarán a la cola de hilos que esperan el cerrojo y
se reanudarán cuando sean planificados.
© Antonio Tomeu
Control de la Concurrencia en Java:
3 API Estándar
Ø
Ø
Ø
Ø
Ø
El monitor Java tiene no tiene variables de
condición, solo una cola de bloqueo de espera
implícita
La política de señalización es señalar y seguir (SC)
Ø El método (hilo) señalador sigue su ejecución
Ø El hilo(s) señalado(s) pasan del wait-set a la
cola de procesos que esperan el cerrojo
Para dormir a un hilo a la espera de una condición
usamos el método wait (dentro de un método
synchronized)
Es menos fino que una variable de condición
El conjunto de espera para wait es único (wait-set)
© Antonio Tomeu
Control de la Concurrencia en Java:
4 API Estándar
MONITORES EN JAVA: PECULIARIDADES
Ø
Ø
Ø
Ø
Ø
No es posible programar a los hilos suponiendo que recibirán la
señalización cuando la necesiten.
Al no existir variables de condición, sino una única variable
implícita, es conveniente utilizar notifyAll para que todos los
procesos comprueben la condición que los bloqueó:
No es posible señalizar a un hilo en especial. Por tanto:
Ø Es aconsejable bloquear a los hilos en el wait-set con
una condición de guarda en conjunción con notifyAll().
Ø while (!condicion) try {wait();} catch
(InterruptedException e) {return;}
Ø Todos serán despertados, comprobarán la condición y
volverán a bloquearse excepto los que la encuentren
verdadera (que pasan a espera del cerrojo sobre el monitor).
No es aconsejable comprobar la condición de guarda con if
Los campos protegidos por el monitor suelen declararse
private
© Antonio Tomeu
Control de la Concurrencia en Java:
5 API Estándar
Técnica de Diseño de Monitores en Java
1.
2.
3.
4.
Decidir qué datos encapsular en el monitor.
Construir un monitor teórico, utilizando tantas variables
de condición como sean necesarias.
Usar señalización SC en el monitor teórico.
Implementar en java
1.
2.
3.
4.
5.
Escribir un método synchronized por cada procedimiento.
Hacer los datos encapsulados private.
Sustituir cada wait(variable_condición) por una
condición de guarda while(!condicion) try{wait()}…
Sustituir cada send(variable de condición) por una
llamada a notifyAll()
Escribir el código de inicialización del monitor en el
constructor del mismo
© Antonio Tomeu
Control de la Concurrencia en Java:
6 API Estándar
/**Ejemplo de Monitor sencillo. Encapsula una variable protegida por
*la abstraccion y posee una interfaz de dos metodos para
*incrementarla y decrementarla y un tercero para conocer el valor
*del recurso protegido.
*@author Antonio Tomeu
*/
class Monitor
{
private static int Dato; //recurso protegido
public Monitor(int VInic){Dato=VInic;}
public synchronized void INC()
{
while(!(Dato<=0))
try{System.out.println("Hilo Sumador bloqueado");
wait();
} catch (InterruptedException e){}
Dato++;
notifyAll();
}
© Antonio Tomeu
Control de la Concurrencia en Java:
7 API Estándar
public synchronized void DEC()
{
while(!(Dato>0))
try{System.out.println("Hilo Restador bloqueado");
wait();
} catch (InterruptedException e){}
Dato--;
notifyAll();
}
public synchronized String toString()
{return(new Integer(Dato).toString());}
}
class HiloSumador
extends Thread
{
private Monitor Data;
public HiloSumador(Monitor Ref){Data=Ref;}
public void run()
{
for(;;)Data.INC();
}
}
© Antonio Tomeu
Control de la Concurrencia en Java:
8 API Estándar
class HiloRestador
extends Thread
{
private Monitor Data;
public HiloRestador(Monitor Ref){Data=Ref;}
public void run()
{
for(;;)Data.DEC();
}
}
public class MonitorSimple
{
public static void main(String[] args)
{
Monitor O = new Monitor(1000);
new HiloSumador(O).start();
new HiloRestador(O).start();
new HiloRestador(O).start();
new HiloRestador(O).start();
for(;;)System.out.println(O.toString());
}
Control de la Concurrencia en Java:
9 API Estándar
} © Antonio Tomeu
MONITOR PRODUCTOR-CONSUMIDOR
/**@author Antonio Tomeu
*/
public class Buffer {
private int numSlots = 0;
private double[] buffer = null;
private int putIn = 0, takeOut = 0;
private int cont = 0;
public Buffer(int numSlots) {
this.numSlots = numSlots;
buffer = new double[numSlots];
}
© Antonio Tomeu
Control de la Concurrencia en Java:
10 API Estándar
public synchronized void insertar (double valor)
{
while (cont == numSlots) //condición de buffer
try {
lleno
wait();
}
catch (InterruptedException e) {
System.err.println("wait interrumpido");
}
buffer[putIn] = valor;
putIn = (putIn + 1) % numSlots;
cont++;
notifyAll(); //inserción en e.m.
}
© Antonio Tomeu
Control de la Concurrencia en Java:
11 API Estándar
public synchronized double extraer () {
double valor;
while (cont == 0) //condición de buffer vacío
try {
wait();
} catch (InterruptedException e) {
System.err.println("wait interrumpido");
}
valor = buffer[takeOut];
takeOut = (takeOut + 1) % numSlots;
cont--;
notifyAll();
return valor; //extracción en e.m.
}
}//Buffer
© Antonio Tomeu
Control de la Concurrencia en Java:
12 API Estándar
Diseño de Hilos sobre el Monitor
class Productor implements Runnable {
private Buffer bb = null;
public Productor (Buffer bb) {this.bb = bb;}
public void run() {
double item = 0.0;
while (true) {
bb.insertar (++item);
System.out.println("Produciendo " + item);
}
}//run
}//Productor
© Antonio Tomeu
Control de la Concurrencia en Java:
13 API Estándar
class Consumidor implements Runnable {
private Buffer bb = null;
public Consumidor (Buffer bb) {this.bb = bb;
public void run() {
double item;
while (true) {
item = bb.extraer ();
System.out.println("Consumiendo " + item);
}
}//run
}//Consumidor
© Antonio Tomeu
Control de la Concurrencia en Java:
14 API Estándar
}
public class Prueba_Prod_Con
{
public static void main (String [] args)
{
int ranuras = 10;
Buffer monitor = new Buffer (ranuras);
new Thread(new Productor(monitor)).start();
new Thread(new Consumidor(monitor)).start();
}//main
}//Prueba_Prod_Con
© Antonio Tomeu
Control de la Concurrencia en Java:
15 API Estándar
EJERCICIO
n Aumente el número de lectores y escritores,
y verifique la sincronización
n Diseñe un monitor en java que modele la
abstracción semáforo, dótelo de métodos
wait y signal, y guárdelo en
semaforo.java
n Escriba ahora un protocolo de e.m. con una
instancia de la clase anterior, y guárdelo en
Usa_semaf.java que utilice la cuenta
encapulada en el monitor
n Construya un monitor que dé solución al
problema de los filósofos
© Antonio Tomeu
Control de la Concurrencia en Java:
16 API Estándar