51

Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Embed Size (px)

Citation preview

Page 1: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor
Page 2: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Page 3: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Multitasking es lo que permite que varias actividades ocurran concurrentemente en una computadora

Habiltualmente se ditinguen:₋ Multitasking basada en procesos₋ Multitasking basada en threads (hilos)

Page 4: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Process-based multitasking₋ Permite que los procesos (por ejemplo programas)

corran concurrentemente en una computadora Thread-based multitasking

₋ Permite que partes(tareas) del mismo programa corran concurrentemente en una computadora

₋ La secuencia de código ejecutado para cada tarea define un camino(path) de ejecución independiente llamado thread(hilo) de ejecución.

Page 5: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

En un ambiente que no es multi-thread (single-threaded environment), solo una tarea se ejecuta por vez.

Se desperdician ciclos de CPU por ejemplo esperando por entrada de datos del usuario

Multitasking permite aprovechar esos ciclos desperdiciados.

Page 6: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Algunas ventajas del multitasking basado en threads en comparación con el basado en procesos:₋ Los threads comparten el mismo espacio de

direcciones₋ El cambio de contexto entre threads es

habitualmente menos costoso que entre procesos₋ El costo de la comunicación entre threads es

relativamente bajo

Page 7: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Java soporta thread-based multitasking y proveee facilidades de alto nivel para la programación multihilos

Thread safety es un término que se utiliza para describir el diseño de clases que aseguran que el estado de sus objetos es siempre consistente, aún cuando sean utilizados concurrentemente por múltiples threads

Page 8: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Comparten el proceso que corre el programa

Cada thread en Java es creado y controlado por un único objeto de la clase java.lang.Thread

Los threads hacen que el ambiente de ejecución sea asíncrono, permitiendo realizar distintas tareas concurrentemente

Page 9: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

El entorno de ejecución distingue entre threads del usuario y “deamon” threads (demonios)₋ Mientras un hilo del usuario esté vivo, la JVM no

termina₋ Los demonios ejecutan mientras haya threads del

usuario activos, existen solo para servir a otros threads de usuario

Page 10: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Cuando corremos una aplicación standalone, automáticamente se crea un thread del usuario para ejecutar el método main

Este thread se llama “main thread”

Si no se crean otros threads a partir de este, entonces el programa finaliza cuando se termine de ejecutar el método main

Page 11: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Si se crean otros threads a partir del main thread, estos heredan el estado de thread de usuario.

En este último caso, programa no finalizará cuando se termine el main, sino cuando finalicen todos los threads de usuario

Page 12: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Los threads en java son representados por un objeto de la clase Thread

Se puede implementar un thread de alguna de las siguientes formas:₋ Implementando la interfaz java.lang.Runnable₋ Extendiendo la clase java.lang.Thread

Page 13: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

La interfaz tiene la siguiente especificación:₋ public interface Runnable {

void run(); }

Un thread que sea creado implementando esta interfaz ejecutará el código definido en el método public run()

Page 14: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Una clase implementa la interfaz Runnable y provee el método run() que va a ser ejecutado por el thread. Este objeto es un objeto Runnable.

Se crea un objeto de la clase Thread pasándole un objeto Runnable como argumento al constructor.

Se invoca al método start() sobre el objeto Thread. Este método retorna inmediatamente luego de que el nuevo Thread comienza a ejecutar.

Es método run() del objeto Runnable es ejecutado (eventualmente) por el objeto Thread.

Page 15: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor
Page 16: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Una clase extiende Thread sobrescribiendo el método run() para definir el código a ejecutar por el Thread.

Esta sublcase puede llamar al constructor de la clase Thread utilizando la llamada super()

El método start() heredado de la clase Thread es invocado sobre el objeto que extiende Thread para que este se convierta en elegible para ser ejecutado.

Page 17: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor
Page 18: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Implementando Runnable:₋ Mejor Diseño orientado a objeto₋ Herencia simple o individual ₋ Consistencia

Extendiendo Thread:₋ Código más sencillo

Page 19: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Thread(Runnable threadTarget)

static Thread currentThread()

final String getName()

final void setName(String name)

void run()

final void setDaemon(boolean flag)

final boolean isDaemon()

Page 20: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Los Threads comparten el mismo espacio de direcciones, por ende, pueden compartir recursos.

Hay situaciones críticas en las que se desea que solo un thread a la vez pueda acceder a un recurso compartido.

Java provee mecanismos de sincronización para controlar el acceso a recursos compartidos

Page 21: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

class Counter { private int count = 0; public void increment() {

int n = count; count = n+1;

} }

¿Que pasaría si dos threads comparten un objeto Counter c y ambos intentan ejecutar c.increment() ?

Page 22: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Un lock (o monitor) se utiliza para sincronizar el acceso a un recurso compartido.

Puede asociarse a un recurso compartido.

Los Threads ganan acceso al recurso cuando son los primeros en obtener el lock asociado al mismo

Los locks logran exclusión mutua

Page 23: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

En Java todos los objetos tienen un lock

El lock de cualquier objeto puede ser utilizado para implementar exclusión mutua.

Asociando un recurso compartido con un objeto Java y su lock, el objeto actúa como guardia asegurando acceso sincronizado al recurso

Solo un thread a la vez podrá acceder al recurso controlado por el objeto lock

Page 24: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

La palabra clave synchronized y el lock forman las bases para implementar ejecución sincronizada.

Existen dos variantes:₋ Métodos synchronized₋ Bloques synchronized

Page 25: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Si un método de un objeto debe ser ejecutado de a un thread a la vez, entonces la declaración deberá tener la keyword synchronized

Un thread que intente ejecutar este método deberá primero obtener el lock del objeto antes de poder ejecutar

El lock se “solicita” invocando el método

Page 26: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Mientras un thread está dentro de un método synchronized, todos los demás threads que intenten ejecutar este método u otros métodos synchronized del objeto deberán esperar

Esta restricción no se aplica al objeto que tenga el lock

Los métodos estáticos sincronizan con el lock de la clase (independiente del lock de los objetos de la clase)

Page 27: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public Object pop() { synchronized (this) {

// Synchronized block on current // object

// ... }

} También puede especificarse el lock de una clase:

₋ synchronized (<class name>.class) { <code block> }

Page 28: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Los siguientes dos segmentos de código son equivalentes:

public void push(char c) {synchronized(this) {:}

}

public synchronized void push(char c) {:

}

Page 29: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor
Page 30: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor
Page 31: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Testeando threads:₋ isAlive() – determina si el hilo está vivo.

Accediendo a thread priority:₋ getPriority()₋ setPriority()

Poniendo threads en espera:₋ Thread.sleep()₋ join()₋ Thread.yield()

Page 32: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public static void main(String[] args) { Thread t = new Thread(new Runner());

t.start(); ... // Do stuff in parallel with the other thread for a while

... // Wait here for the timer thread to finish try { t.join(); } catch (InterruptedException e) {

// t came back early } ... // Now continue in this thread

... }

Page 33: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public class MyThread extends Thread { public void run() { while (running) {

// do lots of interesting stuff try { sleep(100); } catch (InterruptedException e) {

// sleep interrupted } } }

public static void main(String args[]) { Thread t = new MyThread(); t.start(); } }

Page 34: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor
Page 35: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Es cuando dos threads esperan cada uno por un lock de parte del otro

No es detectado o evitado

Puede ser evitado mediante:₋ Decidir el orden para obtener locks₋ Adherirse a este orden durante todo el proceso₋ Liberar los locks en el orden inverso

Page 36: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Escenario:₋ Considere que ud. y el chofer de un taxi son dos

threads

El problema:₋ Cómo determinar cuándo está ud. en su destino?

La solución:₋ Le comunica al chofer sobre su destino y se relaja₋ El taxista conduce y lo notifica cuando arriba a su

destino

Page 37: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Los métodos utilizados son wait y notify

Existen dos pooles:₋ wait₋ lock

Page 38: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor
Page 39: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Deja los datos compartidos en un estado consistente

Asegura que los programas no pueden estancarse

No coloca threads que esperan diferentes notificaciones en el mismo pool de wait

Page 40: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public void run() { char c;

for (int i = 0; i < 200; i++) { c = (char)(Math.random() * 26 +'A'); theStack.push(c); System.out.println("Producer" + num + ": " + c); try { Thread.sleep((int)(Math.random() * 300)); } catch (InterruptedException e) { // ignore it

} } }

Page 41: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public void run() { char c; for (int i = 0; i < 200; i++) { c = theStack.pop(); System.out.println("Consumer" + num + ": " +

c);

try { Thread.sleep((int)(Math.random() * 300)); } catch (InterruptedException e) { }

} }

Page 42: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public class SyncStack {private List buffer = new ArrayList(400);public synchronized char pop() {}public synchronized void push(char c) {}

}

Page 43: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public synchronized char pop() { char c; while (buffer.size() == 0) { try { this.wait(); } catch (InterruptedException e) { // ignore it...

} } c = ((Character)buffer.remove(buffer.size()-

1)).charValue(); return c; }

Page 44: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

public synchronized void push(char c) {this.notify();Character charObj = new Character(c);buffer.addElement(charObj);

}

Page 45: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

A continuación veremos un ejemplo clásico: Productor/Consumidor. Tenemos 2 productores y 2 consumidores, los cuales utilizan un mismo recurso.

En este ejemplo se, maneja la concurrencia al recurso compartido, el cual es producido por prodT1 y prodT2 y consumido por c1 y c2.

Page 46: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

La clase Productor, implementa la interfaz Runnable. En su método run, produce todos los elementos y los coloca en la pila.

Entre que coloca un elemento y otro, se ejecuta el método sleep, de manera de dormir el thread por unos instantes, de manera que otros productores tengan acceso a la pila para colocar sus elemento producidos, o bien un consumidor consuma de la misma.

Page 47: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Ahora veremos el código correspondiente a un Consumidor.

Análogamente, el Consumidor también implementa la interfaz runnable. El método run, es muy similar al de la clase Productor, solo que en este caso, se consume de la pila.

Page 48: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

La clase syncstack, es quien maneja la concurrencia al stack, mediante los métodos push y pop, ya que hace uso de los métodos wait() y notify(), de manera que mediante el wait, el thread espera para obtener el bloqueo y el notify, le avisa que ya termino y el recurso esta libre.

A continuación veremos un ejemplo.

Page 49: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Producer2: FConsumer1: FProducer2: KConsumer2: KProducer2: TProducer1: NProducer1: VConsumer2: VConsumer1: NProducer2: VProducer2: UConsumer2: UConsumer2: VProducer1: FConsumer1: FProducer2: MConsumer2: MConsumer2: T

Page 50: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

Page 51: Multitareas Hilos – Procesos Locks Monitores Deadlocks Ejemplos: productor y consumidor

The Java TutorialTrail de Threadshttp://java.sun.com/docs/books/tutorial/index.html