Asignatura 780014
Programación Avanzada
Tema 5 – Sincronización, interbloqueo y control de hilos
©
[email protected]
wait() fuera de synchronized
public class Error {
int i = 0;
public static void main(String argv[]) {
Error w = new Error();
w.amethod();
}
public void amethod() {
while (true) {
try {
wait();
} catch (InterruptedException e) {
}
i++;
}//End of while
}//End of amethod
}//End of class
¿Qué hace este programa?
run:
Exception in thread "main"
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at Error.amethod(Error.java:11)
at Error.main(Error.java:6)
Java Result: 1
Estados de un Java Thread
Waiting
wait()
notify()
Transición entre estados de un thread
Alive
Not Alive
Dead
Created
start()
Runnable
return
Sleeping
interrupt()
Interrupted
El cambio entre estados de un Java Thread se puede controlar
Y el estado verificar desde el mismo y otros hilos.
Tenemos métodos:
Para controlar la finalización y verificarla
Interrumpir y vericar la interrupción
Dormir un hilo.
Control de finalización de un Thread
Los métodos permite verificar la vivacidad de un hilo y esperar
hasta la finalización de un hilo
final boolean isAlive()
– Devuelve ‘true’ si el thread se encuentra ‘vivo’, es decir, ya ha comenzado
y aun no ha terminado.
final void join() throws InterruptedException
– Suspende el thread que invoca hasta que el thread invocado haya
terminado.
final void join(long milliseg) throws InterruptedException
– Suspende el thread que invoca hasta que el thread invocado haya
terminado o hasta que hayan transcurrido los milisegundos.
Interrupción de Threads
Los métodos permite interrumpir y verificar si un hilo está
interrumpido
void interrupt();
– El thread pasa a estado Interrupted.
– Si está en los estados Waiting, Joining o Sleeping termina y lanza la excepción
InterruptedException.
– Si está en estado Runnable, continua ejecutándose aunque cambia su estado a
Interrupted.
static boolean interrupted();
– Método estático. Devuelve ‘true’ si el thread que lo invoca se encuentra en estado
Interrupted.
– Si estuviese en el estado Interrupted lo pasa al estado Runnable.
boolean isInterrupted();
– Devuelve ‘true’ si el thread en que se invoca se encontrase en el estado Interrupted.
– La ejecución de este método no cambia el estado del thread.
Ejemplo de isInterrupted()
public class InterruptCheck
{
public static void main(String[] args) {
Thread t=Thread.currentThread();
System.out.println("A:t.isInterrupted()="+ t.isInterrupted());
t.interrupt();
System.out.println("B:t.isInterrupted()="+ t.isInterrupted());
System.out.println("C:t.isInterrupted()="+ t.isInterrupted());
try{
Thread.sleep(2000);
System.out.println("No ha sido interrumpida");
}catch(InterruptedException e){
System.out.println("Si ha sido interrumpida");
}
System.out.println("D:t.isInterrupted()="+ t.isInterrupted());
}
Resultado:
run:
A:t.isInterrupted()=false
B:t.isInterrupted()=true
C:t.isInterrupted()=true
No ha sido interrumpida
D:t.isInterrupted()=false
Ejemplo de finalización por InterruptedException
public class Ejemplo1 {
public static void main(String[] args){
Thread hilo= new Hilo1();
hilo.start();
try{
Thread.sleep(1000);
}catch (InterruptedException e){};
hilo.interrupt();
}
}
public class Hilo1 extends Thread{
public void run(){
while (true) {
System.out.println("Ejecuto");
try{
Thread.sleep(100);
}catch (InterruptedException e){
System.out.println("Me despiertan");
return;
}
}
}
}
Resultado:
run:
Ejecuto
Ejecuto
Ejecuto
Ejecuto
Ejecuto
Ejecuto
Me despiertan
Ejemplo de uso de interrupt() e interrupted()
public class Ejemplo2 {
public static void main(String[] x){
Thread hilo= new Hilo2();
hilo.start();
try{
Thread.sleep(1000);
}catch (InterruptedException e){};
hilo.interrupt();
}
}
public class Hilo2 extends Thread{
public void run(){
while (!Thread.interrupted()) {
System.out.println("Ejecuto");
}
System.out.println(“Termino");
return;
}
}
Resultado:
run:
Ejecuto
Ejecuto
Ejecuto
Ejecuto
…
Termino
GENERACIÓN CORRECTA (total time: 2 seconds)
Interrupción durante sleep()
public class SleepInterrupt implements Runnable {
public void run(){
try {
System.out.println(“En run(): me duermo 20 s");
Thread.sleep(20000);
System.out.println(“En run(): me despierto");
}catch (InterruptedException e){
System.out.println(”En run(): despertado");
return;
}
System.out.println(“En run(): fin normal");
}
public static void main(String[] args) {
SleepInterrupt si=new SleepInterrupt();
Thread t=new Thread(si);
t.start();
try{
Thread.sleep(1000);
}catch (InterruptedException e){};
System.out.println(“En main(): Interrumpo a t");
t.interrupt();
System.out.println(“En main(): termino");
}}
Resultado:
Run:
En run(): me duermo 20 s
En main(): Interrumpo a t
En run(): despertado
En main(): termina
Interrupción pendiente y sleep()
public class PendingInterrupt
{
public static void main(String[] args)
{
if (args.length>0) { Thread.currentThread().interrupt();}
long tiempoInicial=System.currentTimeMillis();
try
{
Thread.sleep(2000);
System.out.println("No es interrumpida");
}
catch (InterruptedException e)
{ System.out.println("Es interrumpida"); }
System.out.println("Tiempo gastado: "+
(System.currentTimeMillis()-tiempoInicial));
}
}
Resultado de ejecutar
> java PendingInterrupt
No es interrumpida
Tiempo gastado: 2000
Resultado de ejecutar
> java PendingInterrupt no
Es interrumpida
Tiempo gastado: 0
Interbloqueo
Deadlock
Jeff Magee
Jeff Kramer
Conceptos:
•Un interbloqueo (deadlock) impide que un programa progrese.
Tienen que darse cuatro condiciones necesarias y suficientes
Propósito: Evitar deadlocks => diseñar sistemas en
los que no puedan ocurrir intebloqueos.
Interbloqueo
Ejemplo: Los Filósofos comensales
(Dijkstra)
Cinco filósofos están sentados alrededor de
una mesa circular.
– Cada uno de ellos alterna entre “pensar” y
“comer”.
2
3
3
4
– En medio de la mesa hay un gran plato de
4
0
2
1
1
spaghetti y cada filósofo necesita dos
tenedores para poder comer.
– Como los filósofos cobran menos que los
informáticos, solo tienen 5 palillos en total.
– Hay un tenedor colocado a la izquierda y otro
a la derecha de cada uno.
0
Edsger W. Dijkstra
(1930-2002)
Diagrama del modelo
Cada tenedor es un
recurso compartido
– Dos métodos: get() y put().
Cuando un filósofo tiene
hambre:
– Toma primero su tenedor
derecho y después el
izquierdo
– Con los dos tenedores se
puede poner a comer
phil[4]:PHILphil[1]:PHILphil[3]:PHILphil[0]:PHILphil[2]:PHILFORKFORKFORKFORKFORKleftrightrightrightrightleftleftrightleftleft Interbloqueo
Tal y como está planteado el problema, al cabo de un tiempo más o menos
largo, ocurrirá que cada filósofo tiene un tenedor en su mano derecha y
ninguno puede continuar. Los procesos están interbloqueados
Al cabo de un
tiempo…
Ejecutar Applet
Implementación en Java
Diagrama de clases
Filosofos:
– threads
Tenedores:
– monitores
Diners:
– applet de
visualización
AppletDinersThreadPhilosopher1nFork1nPhilCanvasdisplaycontrollerviewdisplay La calse Fork (Tenedor)
class Fork
{
private boolean taken=false;
private PhilCanvas display;
private int identity;
Fork(PhilCanvas disp, int id)
{ display = disp; identity = id;}
synchronized void put()
{
taken=false;
display.setFork(identity,taken);
notify();
}
synchronized void get()
throws java.lang.InterruptedException
{
while (taken) wait();
taken=true;
display.setFork(identity,taken);
}
}
La clase Filosofo
// thinking
class Philosopher extends Thread
{
...
public void run()
{
try {
while (true)
{
view.setPhil(identity,view.THINKING);
sleep(controller.sleepTime()); // hungry
view.setPhil(identity,view.HUNGRY);
right.get();
view.setPhil(identity,view.GOTRIGHT);
sleep(500);
left.get();
view.setPhil(identity,view.EATING);
sleep(controller.eatTime());
right.put();
left.put();
}
} catch (java.lang.InterruptedException e){}
}
}
// gotright chopstick
// eating
La clase Diners
Creación de los threads filosofod y
los monitores fork:
for (int i =0; i<N; ++i)
fork[i] = new Fork(display,i);
for (int i =0; i<N; ++i){
phil[i] =
new Philosopher
(this,i,fork[(i-1+N)%N],fork[i]);
phil[i].start();
}
La clase PhilCanvas
Es donde se pinta la mesa con los filósofos de colores
alrededor. Estos pueden verse como:
pensando
hambriento
con tenedor derecho
con tenedor izquierdo
comiendo
4 Condiciones para el interbloqueo
1. Recursos compartidos reutilizables en serie,
protegidos mediante exclusión mutua.
2. Asignación parcial de recursos. Cada
proceso va adquiriendo (y bloqueando) los
recursos a medida que los va necesitando.
3. No expulsión de recursos. Una vez adquirido
un recurso, no se libera hasta no haber
adquirido el resto.
Comentarios de: Tema 5 - Sincronización, interbloqueo y control de hilos - Programación Avanzada (0)
No hay comentarios