Está en la página 1de 31

Introducción a la Concurrencia

en Java

Departamento de Lenguajes y Ciencias de la Computación


E.T.S. Ingeniería Informática
Universidad de Málaga

Contenido

– Creación de Hebras
• La clase Thread
• La interfaz runnable
• Hebras como objetos autónomos
• Paso de parámetros
• Finalización
• Estados de una hebra
• Prioridades
• Ejemplos
– Sincronización en Java

Departamento de Lenguajes y Ciencias de la Computación.


2
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 1


Introducción

z Un Proceso
– Contiene su propio espacio virtual de direcciones
• Es distinto para cada proceso
– Contiene una o más hebras (threads) de ejecución
• La hebra es la unidad básica de ejecución
• Las hebras se planifican siguiendo criterios clásicos
– disponibilidad de recursos
– prioridades
– justicia
• Cada hebra tiene su propia pila, variables locales y
contador de programa
• Los cambios de contexto son muy rápidos

Departamento de Lenguajes y Ciencias de la Computación.


3
Universidad de Málaga

Introducción

z Los procesos además contienen


– Uno o varios segmentos de código
– Uno o varios segmentos de datos para las variables
globales
– Información del entorno de ejecución
• Cadenas de caracteres con información variable
– path
– parámetros del entorno
– ....
– El heap del proceso
– Recursos
• Manejadores abiertos
• ....

Departamento de Lenguajes y Ciencias de la Computación.


4
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 2


Creación de hebras

– Creación
Thread th;
th = new Thread ();

– La clase Thread se encuentra en java.lang.Thread


– Una vez creadas, las hebras se pueden configurar y
ejecutar (método start de la hebra)
– Posteriormente el método start llamará al método run de
la hebra
– Existen dos formas de crear hebras
• Heredando de la clase Thread y redefiniendo el método run
• Implementando la Interfaz runnable

Departamento de Lenguajes y Ciencias de la Computación.


5
Universidad de Málaga

Creación de hebras
class HerenciaThread extends Thread {
String m_palabra; // palabra a imprimir
int m_pausa; // duración de la pausa

HerenciaThread (String palabra, int pausa)


{ m_palabra = palabra; m_pausa = pausa; }

public void run( ) {


try { for (int i=0;i<100;i++) {
System.out.print (m_palabra+ " ");
sleep (m_pausa); // puede arrojar excepción
}
} catch (InterruptedException e) {}
}
Departamento de Lenguajes y Ciencias de la Computación.
6
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 3


Creación de hebras
public static void main(java.lang.String[] args) {
HerenciaThread a;
HerenciaThread b;

a=new HerenciaThread (“a",33);


b=new HerenciaThread (“b",100);
a.start();
b.start();
}

Departamento de Lenguajes y Ciencias de la Computación.


7
Universidad de Málaga

Creación de hebras. Interfaz Runnable

class RunThread implements Runnable {


String m_palabra;
int m_pausa;

RunThread (String palabra, int pausa)


{ m_palabra = palabra; m_pausa = pausa; }

public void run() {


try {
for (int i = 0;i<100;i++) {
System.out.println (m_palabra+ " ");
sleep (m_pausa);
}
} catch (InterruptedException e) { // Tratamiento excepción}
}
Departamento de Lenguajes y Ciencias de la Computación.
8
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 4


Creación de hebras

public static void main (String args[]) {

RunThread a = new RunThread (“a",33);


RunThread b = new RunThread (“b",100);

Thread t1 = new Thread (a);


Thread t2 = new Thread (b);

t1.start();
t2.start();
}
}
Departamento de Lenguajes y Ciencias de la Computación.
9
Universidad de Málaga

Hebras como objetos autónomos


z Creación y ejecución automática

class AutoThread implements Runnable {


private Thread me;

public AutoThread()
{ me = new Thread(this);
me.start(); }

public void run() {


for (int i=0;i<10;i++)
System.out.println ("Dentro de Autothread.run()");
}

public static void main(java.lang.String[] args) {


AutoThread mythread = new AutoThread();
for (int i = 0;i<10;i++)
System.out.println ("Dentro de Main()");
}
}
Departamento de Lenguajes y Ciencias de la Computación.
10
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 5


Paso de parámetros
z Necesidad de aceptar parámetros
– El método run() no acepta parámetros
– Solución: utilizar constructores con parámetros

class Worker implements Runnable {


private int parm1, parm2;

public Worker (int p1, int p2) {


parm1 = p1; parm2 = p2; ...
}

public void run() {


System.out.println ("p1 = "+ parm1 + "\np2 = " + parm2);
}
..................
public static void main (String[] args) {
new Worker (3,5); ...
}

Departamento de Lenguajes y Ciencias de la Computación.


11
Universidad de Málaga

Finalización

z Cuatro formas de finalización:


– Terminación del método run()
– Invocación del método stop() por cualquier thread
• Se liberan cerrojos
– Invocación de System.exit() o Runtime.exit() desde
cualquier thread (terminando todos los threads)
– Excepción en el método run()
• Se liberan cerrojos

z Suspensión de un thread:
– suspend()
– resume()
z Comprobación de terminación
– isAlive()

Departamento de Lenguajes y Ciencias de la Computación.


12
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 6


Estados de un thread

Departamento de Lenguajes y Ciencias de la Computación.


13
Universidad de Málaga

Prioridades
z Ejecución del thread de mayor prioridad
– Ejecución de threads de menor prioridad por bloqueos
z Prioridad inicial: la misma que el objeto que crea el thread
z Cambio de prioridad: setPriority()
– Valores entre MIN_PRIORITY y MAX_PRIORITY
– Valor por defecto: NORM_PRIORITY

z Obtención de prioridad actual: getPriority()


z Ceder la CPU: yield()
– ¡El thread elegido puede incluso ser el mismo que cede la
CPU!
z Threads daemon:
– Ejecución continua en background. Prioridad mínima
– Finalización de la aplicación cuando acaben hebras NO
daemon
– Método setDaemon

Departamento de Lenguajes y Ciencias de la Computación.


14
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 7


Ejemplo. Necesidad de exclusión mutua
public class ExMutua {
public static void main(String[] args) {
compartida v;
sumador[] s;

v= new compartida(2);
s = new sumador[2];

for (int i=0; i<2; i++) {


s[i]= new sumador(i,v);
s[i].start();
}
while ((s[0].isAlive()) || (s[1].isAlive())) ; // Espera activa
v.imprime();
}
}

Departamento de Lenguajes y Ciencias de la Computación.


15
Universidad de Málaga

Ejemplo. Necesidad de exclusión mutua (II)

public class compartida {

private int valor;

public compartida() {
valor = 0;
}

public void imprime() {


System.out.println("El valor es: "+valor);
}

Departamento de Lenguajes y Ciencias de la Computación.


16
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 8


Ejemplo. Necesidad de exclusión mutua (III)
public class compartida {
...

public void incrementa() {


int temp;
try{
temp=valor;
temp=temp+1;
if (Math.random()>0.8) Thread.sleep(100);
valor=temp;
}
catch(Exception e) {}
}
}

Departamento de Lenguajes y Ciencias de la Computación.


17
Universidad de Málaga

Ejemplo. Necesidad de exclusión mutua (IV)

public class sumador extends Thread {

private compartida mi_c;


private int mi_id;

public sumador(int id,compartida c) {


mi_c=c;
mi_id=id;
}

public void run() {


System.out.println(“Arranca el sumador: “+mi_id);

for (int i=0; i< 10; i++) {


mi_c.incrementa();
}
}
}
Departamento de Lenguajes y Ciencias de la Computación.
18
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 9


Ejemplo. Suma de matrices concurrente
public class sumap {
public static void main(String args[]) {
int a[][],b[][],resul[][], filas,columnas;

// Inicialización
filas=...; columnas=...;
a=new int[filas][columnas];
b=new int[filas][columnas];
resul=new int[filas][columnas];
...
// Crear hebras sumadoras de filas
sumafila s[]=new sumafila[filas];
for (f=0;f<filas;f++) {
s[f]=new sumafila(a[f],b[f]);
s[f].start();
}
// Esperar la terminación e imprimir resultado...
}}

Departamento de Lenguajes y Ciencias de la Computación.


19
Universidad de Málaga

Ejemplo. Suma de matrices concurrente (II)


public class sumafila extends Thread {
private int a[],b[],resul[];

public sumafila(int ma[],int mb[]) {


a=ma; b=mb;
resul=new int[a.length];
}

public void run() {


int col;
for (col=0;col<a.length;col++)
resul[col]=a[col]+b[col];
}

public int[] resultado() {


return resul;
}
}

Departamento de Lenguajes y Ciencias de la Computación.


20
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 10


Contenido

– Creación de Hebras
– Sincronización en Java
• Exclusión mutua en Java
• Métodos sincronizados
• La sentencia synchronized
• Comunicación entre hebras: wait y notify
• Ejemplo del buffer acotado
• Problema de los filósofos
• Lectores-Escritores
• Herencia y sincronización

Departamento de Lenguajes y Ciencias de la Computación.


21
Universidad de Málaga

Exclusión mutua en Java

z Versión del modelo clásico de monitores


– Mecanismo de más alto nivel que los semáforos
z Sincronización sobre instancias de clases
– synchronized en métodos
– synchronized como sentencia

Sólo una hebra puede estar a la vez utilizando un


bloque synchronized de los que tenga una
instancia de un objeto

(Se pueden seguir llamando a bloques no sincronizados


de la instancia del objeto)

Departamento de Lenguajes y Ciencias de la Computación.


22
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 11


Exclusión mutua en Java (II)

Hebra A
synchronized

Hebra B synchronized

No synchronized
Hebra C

Departamento de Lenguajes y Ciencias de la Computación.


23
Universidad de Málaga

Métodos sincronizados

z Utilización de synchronized en la cabecera del


método
– Una vez que una hebra esté ejecutando un método
sincronizado, ninguna otra hebra puede ejecutar otro
método sincronizado de la misma instancia.

synchronized public int coger ( ) {


return vector[--cima];
}
synchronized public void poner (int elem) {
vector[cima]=elem;
cima++;
return;
}
Departamento de Lenguajes y Ciencias de la Computación.
24
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 12


La sentencia synchronized
z Utilización de synchronized en bloques
arbitrarios de código sobre objetos
– Permiten la utilización de clases no diseñadas para
entornos concurrentes.
synchronized (objeto) sentencia;
public static void abs (int[] values) {
synchronized (values) {
for (int i = 0; i< values.length; i++)
if (values[i[ < 0)
values [i] = -values[i];
}
}

Departamento de Lenguajes y Ciencias de la Computación.


25
Universidad de Málaga

La sentencia synchronized
z Ej: sacar dinero en cajero

public class Cuenta {


public void sacarDinero(int cantidad);
puhlic boolean haySaldo(int cantidad);
}

Cuenta c;
synchronized (c) {
if (c.haySaldo(cantidad))
c.sacarDinero(cantidad);
}

Departamento de Lenguajes y Ciencias de la Computación.


26
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 13


Comunicación entre hebras: wait y notify

z wait y notify para comunicación entre hebras


z Utilización dentro de bloques sincronizados
z wait():
– Liberación del “cerrojo” asociado al objeto
– Hebra dormida hasta invocación de notify() sobre la
misma instancia por otra hebra
z notify():
– Selección de una hebra arbitraria dormida sobre la
misma instancia para pasar al estado listo
z notifyAll():
– Todas las hebras dormidas por un wait sobre una
instancia son despertadas

Departamento de Lenguajes y Ciencias de la Computación.


27
Universidad de Málaga

Comunicación entre hebras: wait y notify (II)


z Ejemplo de utilización de wait()

synchronized void esperarCondicion() {


while (!condicion)
try {
wait();
}
catch (InterruptedException ex) {
// código para manejar la excepción
}
}

Departamento de Lenguajes y Ciencias de la Computación.


28
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 14


Comunicación entre hebras: wait y notify (III)

z Aspectos a tener en cuenta


– Ejecución dentro de un synchronized
– Liberación del cerrojo y suspensión de la hebra de
forma atómica
• Evita problemas por notifys intercalados entre liberación y
suspensión
– Prueba de la condición en un bucle
• Que la hebra despierte no quiere decir que la condición se
cumpla

Departamento de Lenguajes y Ciencias de la Computación.


29
Universidad de Málaga

Comunicación entre hebras: wait y notify (IV)


z Ejemplo de utilización de notify()

synchronized void cambiarCondicion() {


// cambiar algún valor usado en alguna condición
condicion=!condicion;
if (condicion)
notify(); // o notifyAll
}

Departamento de Lenguajes y Ciencias de la Computación.


30
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 15


Ejemplo del buffer acotado
z Buffer acotado
– Múltiples consumidores
– Múltiples productores
– Exclusión mutua para lectura y escritura
P
C

C D

cima P
C
P
Departamento de Lenguajes y Ciencias de la Computación.
31
Universidad de Málaga

Ejemplo del buffer acotado (II)


public class Buffer { // no es un Thread
private int cima, capacidad, vector[];

Buffer (int i) {
cima = 0;
capacidad = i;
vector = new int[i];
}

synchronized public int coger ( ) {


while (cima == 0)
try {
wait();
} catch (InterruptedException e){;}
notifyAll(); // Ya hay sitio en el buffer
return vector[--cima];
}

Departamento de Lenguajes y Ciencias de la Computación.


32
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 16


Ejemplo del buffer acotado (III)

synchronized public void poner (int elem) {


while (cima==capacidad-1)
try {
wait();
} catch (InterruptedException e){;}

vector[cima]=elem;
cima++;
notifyAll(); // Ya hay elementos producidos
}
}

Departamento de Lenguajes y Ciencias de la Computación.


33
Universidad de Málaga

Ejemplo del buffer acotado (IV)


public class Consumer extends Thread {
int elem;
Buffer buffer;

Consumer (Buffer b, int i) {


System.out.println ("entra el consumidor "+i);
buffer = b;
}

public void run ( ) {


try {
elem = buffer.coger();
} catch (Exception e) {;}
System.out.println ("he cogido el elemento: "+elem);
}
}

Departamento de Lenguajes y Ciencias de la Computación.


34
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 17


Ejemplo del buffer acotado (V)
public class Producer extends Thread {
Buffer buffer;
int elem;

Producer (Buffer b, int i) {


elem=i;
buffer = b;
System.out.println ("entra el productor "+i);
}

public void run ( ) {


try {
buffer.poner(elem);
} catch (Exception e) {;}
System.out.println ("he puesto el elemento "+elem);
}
}

Departamento de Lenguajes y Ciencias de la Computación.


35
Universidad de Málaga

Ejemplo del buffer acotado (VI)


public class ConsumerProducer {
static Buffer buf = new Buffer(3);

public static void main (java.lang.String[] args ) {


for (int i=1;i<=5;i++)
new Producer(buf,i).start();

for (int j=1;j<=5;j++)


new Consumer(buf,j).start();

System.out.println ("Fin de la hebra main");


}
}

Departamento de Lenguajes y Ciencias de la Computación.


36
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 18


Problema de los filósofos
z Objetivo:
– Obtener los dos tenedores para poder comer
z Tenedores compartidos con los filósofos vecinos
– Los filósofos no pueden compartir los tenedores

Departamento de Lenguajes y Ciencias de la Computación.


37
Universidad de Málaga

Problema de los filósofos (II)

z Problemas:
– Si todos los filósofos cogen un tenedor:
• ¡Interbloqueo!
– Evitar injusticias:
• Que todos tengan las mismas posibilidades de comer
z Solución propuesta:
– Una clase “controladora” almacena el número de
tenedores disponibles para cada filósofo
– Sólo se permite comer si se tienen los dos tenedores
disponibles.
• Al menos un filósofo podrá comer
• Todos tienen las mismas posibilidades para comer

Departamento de Lenguajes y Ciencias de la Computación.


38
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 19


Problema de los filósofos (III)

public class filosofo extends Thread {


int id;
controlador micontrolador;

public filosofo(int id,controlador c) {


this.id=id;
micontrolador=c;
}

Departamento de Lenguajes y Ciencias de la Computación.


39
Universidad de Málaga

Problema de los filósofos (IV)


public void run() {
do {
System.out.println("Filosofo "+id+" durmiendo");
try {
Thread.sleep((int)(Math.random()*5000));
} catch (Exception e) {
System.out.println(e);
}
micontrolador.coger_tenedor(id);
System.out.println("Filosofo "+id+" comiendo");
try {
Thread.sleep((int)(Math.random()*5000));
} catch (Exception e) {
System.out.println(e);
}
micontrolador.soltar_tenedor(id);
} while (true);
}
}Departamento de Lenguajes y Ciencias de la Computación.
40
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 20


Problema de los filósofos (V)
public class controlador {
int tenedor[],n;

public controlador(int num_filo) {


n=num_filo;
tenedor=new int[n];
for (int cont=0;cont<n;cont++)
tenedor[cont]=2; // 2 tenedores disponibles
}

Departamento de Lenguajes y Ciencias de la Computación.


41
Universidad de Málaga

Problema de los filósofos (VI)


// EL FILOSOFO id COGE SUS TENEDORES
synchronized public void coger_tenedor(int id) {
int sig,ant;

while (tenedor[id] != 2) // ESPERAR 2 TENEDORES


try {
wait(); // ESPERA A TENERLOS
} catch (Exception e) {
System.out.println(e);
}

// MODIFICAR VECINOS
sig=(id+1) % n; ant=id-1;
if (ant<0)
ant=n-1;
tenedor[sig]--;
tenedor[ant]--;
}
Departamento de Lenguajes y Ciencias de la Computación.
42
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 21


Problema de los filósofos (VII)

// EL FILOSOFO id SUELTA SUS TENEDORES

synchronized public void soltar_tenedor(int id) {


int sig,ant;
System.out.println("Filosofo "+id+" termina");
sig=(id+1) % n; ant=id-1;
if (ant<0)
ant=n-1;
tenedor[sig]++; tenedor[ant]++;
notifyAll();
}

Departamento de Lenguajes y Ciencias de la Computación.


43
Universidad de Málaga

Problema de los filósofos (VIII)


public class filos {
public static void main(String args[])
{
controlador c=new controlador(5); // 5 FILOSOFOS
filosofo f[];

// INICIALIZA FILOSOFOS
f=new filosofo[5];
for (int cont=0;cont<5;cont++)
f[cont]=new filosofo(cont,c);

// COMIENZA FILOSOFOS
for (int cont=0;cont<5;cont++)
f[cont].start();
}
}

Departamento de Lenguajes y Ciencias de la Computación.


44
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 22


Lectores - Escritores
z Problema: un recurso que necesita exclusión
mutua entre escritores y lectores pero no entre
múltiples lectores
– Escritura ó lectura
– Múltiples lecturas al mismo tiempo Datos
– Sólo un escritor al mismo tiempo

lector lector escritor escritor

Departamento de Lenguajes y Ciencias de la Computación.


45
Universidad de Málaga

Lectores – Escritores (II)


z Solución: protocolo de entrada/salida
Lector: Escritor:
comenzar_lectura comenzar_escritura
... ...
terminar_lectura terminar_escritura

public class LectoresEscritores


{

private int lectores = 0;


private int escritoresEsperando = 0;
private boolean escribiendo = false;

Departamento de Lenguajes y Ciencias de la Computación.


46
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 23


Lectores – Escritores (III)
public synchronized void ComenzarEscritura()
throws InterruptedException
{
while(lectores > 0 || escribiendo)
{
escritoresEsperando++;
Bucle para
wait(); recomprobar
escritoresEsperando--;
} la condición
escribiendo = true;
}

public synchronized void TerminarEscritura()


{
escribiendo = false;
notifyAll(); Despertar a todos
}
Departamento de Lenguajes y Ciencias de la Computación.
47
Universidad de Málaga

Lectores – Escritores (IV)

public synchronized void ComenzarLectura()


throws InterruptedException
{
while(escribiendo || escritoresEsperando>0) wait();
lectores++;
}

public synchronized void TerminarLectura()


{
lectores--;
if(lectores == 0) notifyAll();
}

}
Solución ineficiente, todas las hebras son despertadas
Departamento de Lenguajes y Ciencias de la Computación.
48
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 24


Lectores – Escritores (V)

z Solución 2:
– Objetivo: reducir el número de hebras despertadas
innecesariamente
z Aproximación:
– Utilizar otra clase junto con sincronización de bloques
– Obtener el cerrojo de una variable de condición sobre la
que se querría dormir o despertar y después obtener el
cerrojo para la clase LectoresEscritores

public class VariableCondicion {


public boolean quieroDormir = false;
}

Departamento de Lenguajes y Ciencias de la Computación.


49
Universidad de Málaga

Lectores – Escritores (VI)

public class LectoresEscritores


{

private int lectores = 0;


private int lectoresEsperando = 0;
private int escritoresEsperando = 0;
private boolean escribiendo = false;

VariableCondicion OkParaLeer = new VariableCondicion();


VariableCondicion OkParaEscribir =
new VariableCondicion();

Departamento de Lenguajes y Ciencias de la Computación.


50
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 25


Lectores – Escritores (VII)
public void ComenzarEscritura()
throws InterruptedException
{
synchronized(OkParaEscribir) // acceso a la variable
{
synchronized(this) // exclusión mutua en el método
{
if(escribiendo | lectores > 0) {
escritoresEsperando++;
OkParaEscribir.quieroDormir = true;
} else {
escribiendo = true;
OkParaEscribir.quieroDormir = false;
}
} // Suelto cerrojo del método
if(OkParaEscribir.quieroDormir)
OkParaEscribir.wait();
}
} Observar el orden de las sentencias de sincronización

public void TerminarEscritura()


{
synchronized(OkParaLeer) Lectores – Escritores (VIII)
{
synchronized(OkParaEscribir)
{
synchronized(this)
{
if(escritoresEsperando > 0) {
escritoresEsperando--;
OkParaEscribir.notify(); // despertar 1 escr.
} else {
escribiendo = false;
OkParaLeer.notifyAll(); // despertar lectores
lectores = lectoresEsperando;
lectoresEsperando = 0;
}
} Importante para todos los métodos: usar el
}
}
mismo orden para evitar interbloqueos
}

Tecnología de Objetos para el Desarrollo de Software 26


Lectores – Escritores (IX)
public void ComenzarLectura()
throws InterruptedException
{
synchronized(OkParaLeer) {
synchronized(this)
{
if(escribiendo | escritoresEsperando> 0) {
lectoresEsperando++;
OkParaLeer.quieroDormir = true;
} else {
lectores++;
OkParaLeer.quieroDormir = false;
}
}
if(OkParaLeer.quieroDormir) OkParaLeer.wait();
}
}

Lectores – Escritores (X)


public void TerminarLectura()
{
synchronized(OkParaEscribir)
{
synchronized(this)
{
lectores--;
if(lectores == 0 & escritoresEsperando > 0) {
escritoresEsperando--;
OkParaEscribir.notify();
}
}
}
}
}

Tecnología de Objetos para el Desarrollo de Software 27


Herencia y sincronización

z La combinación del paradigma orientado a objetos


con mecanismos para programación concurrente
puede dar lugar a la llamada anomalía de la
herencia.
z Existe anomalía de la herencia cuando una subclase
añade nuevas operaciones y es necesario cambiar la
sincronización de la clase padre para manejar estas
nuevas operaciones.

Departamento de Lenguajes y Ciencias de la Computación.


55
Universidad de Málaga

Herencia y sincronización (II)


public class BufferCircular
{
private int buffer[];
private int primero;
private int ultimo;
private int cuantos = 0;
private int medida;

public BufferCircular(int lontitud)


{
medida = longitud;
buffer = new int[medida];
ultimo = medida - 1;
primero = medida - 1;
}
};
Departamento de Lenguajes y Ciencias de la Computación.
56
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 28


Herencia y sincronización (III)
public synchronized void put(int item) throws InterruptedException {
if (cuantos == medida)
wait();

ultimo = (ultimo + 1) % medida;


cuantos++;
buffer[ultimo] = item;
notifyAll();
};

public synchronized int get() throwsInterruptedException {


if (cuantos == 0)
wait();

primero = (primero + 1) % medida;


cuantos--;
notifyAll();
return buffer[primero];
};
Departamento
} de Lenguajes y Ciencias de la Computación.
57
Universidad de Málaga

Herencia y sincronización (IV)

z Nueva clase con métodos para permitir el acceso al


buffer

public class BufferCircularSeguro extends BufferCircular {


boolean prohibido ;

BufferCircularSeguro(int longitud)
{
super(longitud);
prohibido = false;
}

Departamento de Lenguajes y Ciencias de la Computación.


58
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 29


Herencia y sincronización (V)

z Permitir acceso y prohibir acceso

public synchronized void prohibirAcceso() throws InterruptedException


{
while (prohibido) wait();
prohibido = true;
}

public synchronized void permitirAcceso() throws AccessError


{
if (!prohibido) throw new AccessError();
prohibido = false;
notifyAll();
}

Departamento de Lenguajes y Ciencias de la Computación.


59
Universidad de Málaga

Herencia y sincronización (VI)

z Redefinición de put y get

public synchronized void put(int item) throws InterruptedException


{
while(prohibido) wait();
super.put(item);
}

public synchronized int get() throws InterruptedException


{
while(prohibido) wait();
return(super.get());
}
}

Departamento de Lenguajes y Ciencias de la Computación.


60
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 30


Herencia y sincronización (VII)

z Problema:
– Sentencias wait y notify de los nuevos put y get interfieren
con los de la clase padre: es necesario modificar la clase
padre
public synchronized void put(int item) throws InterruptedException
{
while (cuantos == medida) {
wait();
};
ultimo = (ultimo + 1) % medida;
cuantos++;
buffer[ultimo] = item;
notifyAll();
};

Departamento de Lenguajes y Ciencias de la Computación.


61
Universidad de Málaga

Herencia y sincronización (VIII)

public synchronized int get() throws InterruptedException


{
while (cuantos == 0) {
wait();
};
primero = (primero + 1) % medida;
cuantos--;
notifyAll();
return buffer[primero];
};

z ¿Más problemas ocultos?

Departamento de Lenguajes y Ciencias de la Computación.


62
Universidad de Málaga

Tecnología de Objetos para el Desarrollo de Software 31

También podría gustarte