1 / 28

Sincronización de Threads en Java

Josep Joan Ribas Prats Sergio Liminiana Bernat. Sincronización de Threads en Java. Introducción. Los threads o hilos de ejecución son segmentos de código de un programa que se ejecutan secuencialmente de modo independiente de otras partes del programa.

amalia
Télécharger la présentation

Sincronización de Threads en Java

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Josep Joan Ribas Prats Sergio Liminiana Bernat Sincronización de Threads en Java

  2. Introducción • Los threads o hilos de ejecución son segmentos de código de un programa que se ejecutan secuencialmente de modo independiente de otras partes del programa. • Un proceso puede estar constituido por uno o mas threads. • Un thread esta compuesto por : • Una CPU virtual • El código que ejecuta el procesador • Los datos sobre los que trabaja el código • Dos threads comparten código si ejecutan código de objetos que pertenecen a la misma clase.

  3. Introducción (II) • Los datos pueden ser o no compartidos por diferentes threads. Eso ocurre cuando tienen acceso a un objeto común.

  4. Para qué? • Los threads se utilizan para aislar y coordinar tareas. • Sin el uso de threads hay aplicaciones que son casi imposibles de programar: • Las que tienen tiempos de espera importantes entre etapas • Las que consumen muchos recursos de CPU e impiden que el procesador atienda simultáneamente otros eventos o peticiones del usuario

  5. Tipos. • Tipos de threads que pueden aparecer en una aplicación: • Threads completamente independientes, que realizan tareas no relacionadas. Éste es el caso más sencillo y no requiere ninguna programación especial. • Threads que trabajan en una misma tarea, pero sin interferir ni intercambiar relación entre ellos. Por ejemplo, threads que colaboran en el producto de dos matrices ocupándose cada una de ellas de calcular ciertas filas de la matriz producto.

  6. Tipos(II). • Threads que utilizan recursos de modo mutuamente exclusivo, aunque sin tener que coordinar sus actividades. Por ejemplo, threads que actualizan o leen registros de una base de datos y que no pueden actuar simultáneamente. • Threads que deben de coordinar sus actividades, de modo que una de ellas no puede empezar o continuar hasta que la otra haya realizado su tarea. Los ejemplos más típicos son los de tipo productor-consumidor, en el que este último tiene que esperar para realizar su función a que el productor le haya preparado los datos y le avise de esa circunstancia.

  7. Creación. • Hay dos modos de conseguir threads en Java. Una es extender la clase Thread, la otra es implementando la interface Runnable.

  8. Creación extendiendo la clase Thread • El nuevo thread se crea extendiendo la clase Thread y redefiniendo el metodo run(). • Exemple: public class MyThread extends Thread{ public void run(){ // código propio del thread } } public static void main(){ Thread t= new MyThread(); t.start; }

  9. Creación implementando la interface Runnable • El constructor de la clase Thread recibe un argumento que debe ser una instancia de una clase que implementa la interface Runnable, implementando el metodo run() .

  10. Creación implementando la interface Runnable(II) • Ejemplo: public class ThreadTest{ public static void main(String args[]{ Xyz r = new XYZ(); Thread t = new Thread( r ); } } class Xyz implements Runnable { int i; public void run(){ while (true){ System.out.println(“Hello” + i++); if (i==50) break; } } }

  11. Qué mecanismo usar? • Implementar la interfaz Runnable: • Mejor diseño orientado a objetos. La clase thread solo deberá ser extendida cuando se pretenda modificar o extender el comportamiento de dicho modelo de ejecución. • Herencia simple. Debido a la tecnología de Java no es posible extender una clase cuando ésta ya ha sido extendida a la clase thread • Extender la clase Thread: • Código más simple. En el método run la referencia this apunta a la instancia del thread actual

  12. Estados de un thread. Otherwise Blocked New sleep() timeout thread join() interrupt() start() sleep() join() run() Runnable Running Dead synchronized() wait() lock available Blocked in objects wait() pool Blocked in objects lock pool notify() interrupt()

  13. Estados de un thread (II). • Nuevo (New): El thread ha sido creado pero no inicializado (no se ha ejecutado todavía el método start()), por lo que todavía no puede ejecutarse. • Ejecutable (Runnable): El thread puede estar ejecutándose, siempre y cuando se le asigne tiempo de CPU. (Scheduler)

  14. Estados de un thread (III). • Muerto (Dead): La forma habitual de morir en un thread es finalizando de ejecutar el método run(), bien por terminar su tarea, bien dejando de cumplir una condición chequeada en dicho método. • Bloqueado (Blocked o Not Runnable): El thread podría estar ejecutándose, pero hay algo que lo impide, como por ejemplo una operación de E/S. Mientras un thread esté en este estado, no se le asigna tiempo de CPU.

  15. Planificación de threads. • La planificación de ejecución de threads se basa en el modelo de prioridades y no utiliza el modelo de segmentación por segmentos de tiempo. • Un thread continuará ejecutandose en la CPU hasta pasar a un estado que no le permita seguir en ejecución. Se debe asegurar que el thread permite la ejecución de otros threads, esto se puede conseguir mediante llamadas al método sleep().

  16. Planificación de threads(II). • Ejemplo: public class Xyz implements Runnable { public void run() { While(true){ // código del propio thread try{ // permitimos la ejecución de otros threads Thread.sleep(10); } catch(InterruptedException e) { // otro thread despierta a este thread } } } • Los threads pueden invocar al método interrupt() de otros threads para reanimarlos.

  17. Planificación de Threads(III). • Otro método para permitir la ejecución de otros threads es el método yield() que permite la ejecución de otro thread con la misma prioridad. • Las prioridades viene definidas por variables miembro de la clase Thread, que toman valores int entre unos valores MAX_PRIORITY y MIN_PRIORITY (entre 1 y 10), siendo la prioridad por defecto NORM_PRIORITY(5).

  18. Planificación de Threads(IV). • Cuando se crea un thread, hereda la prioridad del thread que la ha creado. • Para modificar la prioridad de un thread se utiliza el método setPriority(int), y para obtener su valor el método int getPriority(). • El algoritmo de distribución de recursos en Java: • Es preemptive, es decir, el sistema ejecuta el thread de mayor prioridad entre todos los que son Runnable (excepcionalmente puede ejecutarse otro thread para evitar que algunos procesos “duerman” indefinidamente). • Si varios threads en estado Runnable tienen la misma prioridad se van ejecutando sucesivamente mediante permutación cíclica

  19. Planificación de Threads(V). • Threads Daemon • Los threads daemon llamodos servicios, se ejecutan con prioridad baja y proporcionan un servicio básico a un programa o programas cuando la actividad de la máquina es reducida. • Un ejemplo de thread demonio que está ejecutándose continuamente es el recolector de basura (garbage collector). E • Un thread puede fijar su indicador de demonio pasando un valor true al método setDaemon(). Si se pasa false a este método, el thread será devuelto por el sistema como un thread de usuario. No obstante, esto último debe realizarse antes de que se arranque el thread (start()).

  20. Control básico de threads. • Finalización del la ejecución de un thread. • Cuando un thread acaba su ejecución y es finalizado , no puede volver a ser ejecutado. • Podemos detener un thread utilizando un flag que utiliza un metodo run que debe terminar la ejecución. • r.stopRunning() // r instancia de una clase que implementa runnable

  21. Control básico de threads (II). • Verificación del estado thread isAlived() • boolean isAlived(). Devuelve true si el thread ha sido inicializado con start y no ha terminado el ciclo de ejecución. • Bloqueo de threads. • sleep(). Permite detener un thread durante un determinado tiempo • join(). Bloquea el thread actual, hasta que el thead sobre el cual ha sido ejecutado el join termina.

  22. Sincronización. • Existen muchas situaciones interesantes donde ejecutar threads concurrentes que compartan datos y deban considerar el estado y actividad de otros threads. Este conjunto de situaciones de programación son conocidos como escenarios 'productor/consumidor'; donde el productor genera un canal de datos que es consumido por el consumidor. Como los threads comparten un recurso común, deben sincronizarse de alguna forma.

  23. Sincronización. Uso de synchronized • Cada objeto tiene un “flag de bloqueo” • La palabra clave synchronized permite controlar el flag para activar accesos exclusivos al objeto y cada objeto tendrá asociada una cola de espera. • Se pueden declarar bloques de código synchronized. synchronized ( variableCompartida ) { // acceso al recurso } • Métodos synchronized public synchronized void nomMetode () { // acceso al recurso }

  24. Sincronización. Uso de synchronized • El flag de bloqueo de un objeto se libera : • Cuando el thread termina el bloque de código synchronized • Cuando le bloque de código synchronized lanza una excepción. • Deadlock • Dos threads esperando un flag de bloqueo • No se detecta • Se puede evitar: • Decidir el orden de obtención de los bloqueos • Seguir con rigurosidad ese orden • Liberar los bloqueos en orden inverso

  25. Sincronización. Comunicación entre threads • wait() y notify() • Si un thread ejecuta una llamada wait() sobre un objeto x pausará su ejecución hasta que otro thread ejecute la llamada a notify() mediante el mismo objeto x. • Para poder ejecutar tanto un wait() como un notify() el thread debera disponer del flag de bloqueo, es decir, solo podrán ser ejecutadis desde un bloque de codigo synchronized. • Listas de espera o “pools” • Cuando un thread ejecuta wait() se libera el flag de bloqueo y es colocado en la lista de espera o pool del objeto (wait pool) • Al ejecutar notify() un thread abitrario es movido de la lista de espera hacia una lista de threads que esperan por el flag de bloqueo (lock pool). notifyAll() despierta a todos los threads.

  26. Sincronización. Monitores • Cuando un método synchronized se ejecuta adquiere un monitor sobre el objeto. Cuando un thread tiene el monitor del objeto ningún otro thread podrá ejecutar un metodo synchronized. • Un thread sale del monitor cuando libera el flag de bloqueo del objeto.

  27. Sincronización. Monitores(II). • Un ejemplo típico del uso de monitores es el esquema de productor/consumidor. • Aquí el productor y el consumidor son threads que acceden a la región critica que es la tuberia o buffer. Esta tiene que tener sus métodos protegidos mediante synchronized y tiene que hacer que los threads se comuniquen mediante wait(), notify() y notifyAll().

  28. Bibliografia • Dossier Programación Java (Tomo 2) PUE • http://server2.ok.cl/java/Cap7/thread.html • http://www.medicina.ull.es/aula/tutoriales/java/monitors.html

More Related