73
Capítulo 9: THREADS Carlos Oñate Bravo

Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Embed Size (px)

Citation preview

Page 1: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Capítulo 9: THREADS

Carlos Oñate Bravo

Page 2: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

THREADS

• Start New Threads• lRecognize Thread States and Transitions• Use Object Locking to Avoid Concurrent Access• l Write Code That Uses wait(), notify(), or notifyAll()

Page 3: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Definiendo, Instanciado y Empezando un Hilo

• En java thread significa dos cosas:o Una instancia de java.lang.Trhead

Es un objeto con atributos que vive y muere en el heapo Un thread de ejecucion

Es un proceso individual, con su propia llamada al stack. En java hay un hilo por llamada a stack o una llamada al stack

por hilo.• Cuando se crea un nuevo hilo se materializa un

stack a parte del main, donde corren los metodos invocados en ese hilo.

Page 4: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• EL conceto que hay que saber es:o Cuando se trata de hilo, muy poco es garantizado.o En el examen se espera que uno sepa que es y que no

es garantizado.

Page 5: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Lo que mas va a haber con preguntas sobre hilos• Aquí no se trata de enseñar como elaborar una

aplicación buena, segura y multihilo, solo la punta de un gran capitulo.

• Hay dos tipos de Hilos, el “user” y el “daemon”, los que verán y crearán aquí son de tipo user, cuando mueren los de estos tipos, si existen de los tipo daemon, mueren, no importa en que estado se encuentren.

Page 6: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Creando un Hilo

• Se empieza con una instancia de la clase java.lang.Thread, donde se entontrarán varios metods, pero los minimo que se deben de conocer son:o start()o yield()o sleep()o run()

• Las acciones corren en metodo run(). public void run() { // codigo a ejecutar va aqui. }

• La ejecucion del hilo y creacion del nuevo stack empieza con la llamada al metodo run().

Page 7: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Donde va el metodo run()??? Se puede hacer dos cosas:o Extender de clase java.lang.Threado Implementar la interface Runnable.

• En el mundo real, lo que mas se hace es implementar Runnable, aunque extender seria lo mas facil.

• La unica manera de que tenga sentido que se extienda, es que se haga algo que se sea mas espcializado de la clase Thread.

• Entones si se quiere hacer no mas algo, se tiene que implementar Runnable, lo que nos permite extender de otra clase.

Page 8: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Definiendo un Hilo

• Para definir un hilo se necesita un lugar para definir el metodo run(), y como ya vimos, se puede extender de Thread o implementar Runnable.

Page 9: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Extendiendo de Thread

class MyThread extends Thread {             public void run() {          System.out.println("Importantjob running in MyThread");             }       }

• La limitación en este aspecto es que no se puede extender de otra clase.

• Este metodo se puede sobrecargar, pero el unico metodo que será llamado automaticamente es run(). Los otros se tienen que llamar manualmente.

Page 10: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Implementando Runnable

• Primero, si se implementa, se puede extender de otra clase que se quiera.

class MyRunnable implements Runnable { public void run() { System.out.println("Important job running in MyRunnable"); } }

Page 11: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Instanciando un Thread

• Recordar que cada ejecucion de hilo, necesita una instanciacion de la clase Thread.

• No importa si es que extendio de la clase o se implemento la interfaz, se necesita un hilo, para hacer el trabajo.

• Cuando se extiende es simpleo MyThread t = new MyThread()

• Pero cuando se implementa la interfazo MyRunnable r = new MyRunnable();o Thread t = new Thread(r);

Page 12: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Cuando no se le pasa argumento al constructor, el hilo llama a su propio metodo run().

• El Runnable que se le pasa al constructor es llamado target o runnable target.o Se puede pensar en el Thread como el trabajdor y al

Runnable como el trabajo.• Se puede usar un mismo Runnable para diferentes

Threads public class TestThreads { public static void main (String [] args) { MyRunnable r = new MyRunnable(); Thread foo = new Thread(r); Thread bar = new Thread(r); Thread bat = new Thread(r); } }

Page 13: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Los constructores que se necesita saber son: Thread() Thread(Runnable target) Thread(Runnable target, String name) Thread(String name)

• Cuando se instancia un hilo, se dice que el hilo esta en estado new.

• Una vez que es llamado el metodo start(), su hilo es alive, aunque el metodo run(), no haya sido llamado.

• Su estado pasa a dead cuando su metodo run() ha culminado.

Page 14: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• El metodo isAlive(), es la mejor manera de saber cuando un hilo ha empezado, pero no ha terminado su metodo run().

• El metodo getState() es util para la etapa de debugging, pero no es necesario para el examen.

Page 15: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Empezando un Hilo

• Para empezar el hilo se tiene que llamar a su metodo start().

• Como se dijo anteriormente antes de llamar al metodo start(), el hilo esta en estado new. Se tiene un hilo como instancia, pero no como hilo propiamente dicho.

• Entonces que pasa DESPUES de llamar a start().o Comienza la ejecucion de un nuevo hilo( con el nuevo

call stack).o El hilo se mueve de estado NEW a RUNNABLE.o Cuando el hilo ya tiene la oportunidad para ejeutarse,

su método target, run(), correrá.

Page 16: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Ahora hay que estar seguros que lo que se empieza es el Thread, no un Runnable.

• Ver Hilos1.TestThreads.java

Page 17: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access
Page 18: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Identificación de un Hilo

• Par identificar un hilo se puede hacer uso del método getName(), de la clase Thread.

• Ver ejemplo Hilos1. NameThread.java

• Ojo:o Como en el ejemplo se ha implementado Runnable, la

manera se llamar al hilo actual es atraves de: Thread.currentThread()

o Luego se puede invocar al metodo getName(). Thread.currentThread().getName()

Page 19: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Aun si no se pone un nombre al hilo, se le pone uno por default.

Page 20: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Empezando y corriendo múltiples hilos

• Se creará 3 hilos con el mismo Runnable.• Ver ejemplo Hilos2.ManyNames.java• Puntos a considerar:

o Nada garantiza que los hilos empezaran a correr en el orden que se los manda.

o Tampoco que una vez que haya empezado uno, ese mismo continuará hasta terminar la tarea.

o O que un lazo terminará antes que empiece otro hilo.

IMPORTANTE: Lo UNICO que se puede estar seguros es que:

UN HILO EMPEZARÁ, Y CADA HILO CORRERA HASTA COMPLETARSE.

• Modificar ejemplo Hilos2.ManyNames.java

Page 21: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Por que se dan estos resultados :o Se debe al planificador (scheduler), y nosotros no lo

controlamos.o Los hilos no correrán en el orden en fueron empezadoso No esta garantizado ni orden ni duración.

• Pero hay un modo de decirle a un hilo que no empieze hasta que otro haya acabado, se lo puede hacer con el metodo join().

• UN HILO SE HA COMPLETADO CUANDO HA TERMINADO SU METODO TARGET RUN().

Page 22: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Cuando un hilo termina su método run(), deja de ser un hilo de ejecución.

• El hilo se disuelve y pasa a estado dead.• No es que desaparece de memoria, solo está dead,

pero sigue como un objeto mas, y se puede seguir llamado a sus métodos.

• Lo que no se puede hacer, es volver a llamar al método start().

UNA VEZ QUE UN HILO HA SIDO EMPEZADO, NO PUEDE JAMAS VOLVER A SER EMPEZADO.

Page 23: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Si se vuelve a llamar al metodo start() por segunda vez salta el error IllegalThreadStateException en tiempo de ejecucion.

• Esto pasa aunque el metodo run() haya o no terminado.

• Solo un hilo nuevo puede llamar a start(), y solo lo puede llamar UNA sola vez.

• Un hilo empezado o muerto no puede volver a empezar.

• Los estados que se han visto son:o New, Runnable y Dead.

Page 24: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Planificador de Hilos

• Es partde de la JVM y decide que hilo correra en que momento, tambien saca al hilo del estado run.

• Se asume 1 solo procesador, 1 hilo corre a la vez, solo 1 stack puede correr al mismo tiempo.

• Cuando se dice elegible es que esta en el estado runnable.

• El hilo solo en estado runnable puede ser elegido por el planificador para ser el que pase correr.

EL ORDEN EN QUE EL HILO RUNNABLE ES ELEGIDO, NO ESTA GARANTIZADO.

Page 25: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Algo tipico es el comportamiento de encolar, pero no esta garantizado.

• Esto es que cuando un hilo ha acabado con su turno se va al final del pool para que cuando vuelva al frente vuelva a ejecutarse.

• En realidad se lo llama pool runnable.• Aunque no se puede controlar el planificador, se

puede “influir” en el.

Page 26: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Metodos de la clase Thread

• Metodos que ayudan a influenciar en el planificador:o public static void sleep(long millis)

throwsInterruptedExceptiono public static void yield()o public final void join() throws InterruptedExceptiono public final void setPriority(int newPriority)

• Donde sleep y join tienen metodos sobrecargados.

Page 27: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Metodos de la clase Object

• Metodos heredados de Objet, que estan relacionados con hilos:o public final void wait() throws InterruptedExceptiono public final void notify()o public final void notifyAll()

• El metodo wait tiene metodos sobrecargados.

Page 28: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Estados de Hilos y Transiciones

• Esta parte se trata de cambio de los estados de los hilos.

• De que estado a que estado van???

Page 29: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Estados de Hilos

• Pueden haber solo 5 estados:o New: Cuando un hilo es instanciado, pero no se ha

invocado a start(). Es un objeto hilo pero no un hilo de ejeucion. Aquí es considerado no vivo.

o Runnable: Cuando es elegible para correr, pero el planificador no lo ha elegido. Entra en este estado despues del metodo start(). Puede retornar a este estado depues de estar bloqueado, esperando o en estado sleep. Aquí es considerado vivo.

o Running: Es el estado cuando el planificador ha sido elegido desde el pool. Puede salir de este estado por muchas razones, pero solo una manera de llegar, que sea elegido por el planificador desde el pool.

Page 30: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Waiting/blocking/sleeping: Son los estados en los que son elegibles para correr. En estos estados todavia esta vivo el hilo. o Puede que no este en estado runnable, pero puede retornar a

este estado.o Si esta bloqueado esperando por un recurso, puede retornar al

runnable si es que el obtiene los recursos o el recurso por el que esperaba fue liberado.

o Si esta en sleep, cuando se acaba el perdo de sleep, vuelve al estado runnable.

o Si esta en estado wait, puede volver cuando otro hilo le diga que ya no es necesario que este wait.

• Punto importante: Un hilo no le puede dacir a otro que se bloquee.

Page 31: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Existen métodos estáticos como:o t.sleep() y t.yield()

• Pero asi sean referencias a otros hilos, no los bloquea, de hecho, solo afectan al hilo que esta corriendo.

• NOTA: o existe el metodo suspend() y su opuesto resume() y

stop(), pero son deprecated y no seran parte del examen.

o Se ha considerado sus usos como peligroso.

Page 32: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Dead: Cuando su metodo run() ha terminado. Sigue siendo un objeto Thread, pero ya no es un hilo de ejecucion. Una vez muerto, no se puede regresar a estar vivo. Si esta aquí, y se llama al metodo start() salta un error en tiempo de ejecucion.

Page 33: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Previniendo ejecución de Hilos

• El examen no se conentra en el bloqueo por I/O, si no por:o Waitingo Sleepingo Blocked porque se necesita de un objeto bloqueado.

Page 34: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Sleeping

• Metodo estatico, se lo forza a ir a sleep antes de ponerse en runnable.

• No retorna hasta retornar.• Razones para usar sleep:

o Porque se quiere retardar velocidad.o Para forzar a turnar hilos

• Arroja excepcion InterruptedException en tiempo de compilacion.

• Ver ejemplo Hilos3. ManyNames.java

Page 35: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• En el ejemplo no se puede estar seguro de cual hilo es el que va ser puesto en ejecucion cuando salga del sleep.

• Pero usando sleep(), es la mejor manera de darle oportunidad a un hilo de correr.

• Cuando se hace una llamada a sleep(), debera estar en ese estado por al menos los milisegundos especificados, a menos que sea interrumpido antes que se levante, y en este caso salta la excepcion InterruptedException.

Page 36: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Por último, recordar que sleep() es un método estático, se lo puede poner donde sea.

• El método sleep() pondrá a estado sleep solo al hilo en ejecución actual, el que tiene su propio stack.

Page 37: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Creando un hilo y poniéndolo en sleep

• Crear un hilo que cuente hasta 100 y que pase 1 segundo entre cada numero. Imprima el numero cada multiplo de 10.

Page 38: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Prioridades de hilos y yield()

• Para entender este metodo, es necesario saber la prioridad de hilos.

• Los hilos generalmente corren con una cierta prioridad, que usualmente es un número del 1 al 10.

• Puede que el planificador use time slicing, pero no todas las JVM puede que lo usen.

• Aunque la mayoría de JVM usan time slicing, algunas puede que usen el planificador que permite que el hilo continúe hasta terminar su metodo run().

Page 39: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Cuando un hilo entra en el estado runnable, se le asigna la prioridad mas alta que cualquiera que este en pool y mas alta que el hilo corriendo.

• El que tenga la prioridad mas baja será empujado hacia atrás con estado runnable, y el que tenga prioridad mas alta será el elegido para correr.

• OJO: En cualquier momento el hilo corriendo será de prioridad igual o mayor que el hilo de mayor prioridad en el pool (se contradice, pag 696).

• NUNCA SE DEBE BASAR EN LA PRIORIDAD PARA TRABAJAR CON HILOS.

Page 40: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Algo que no esta garantizado tampoco, es el comportamiento de los hilos cuando tienen igual prioridad o cuando el hilo corriendo tiene igual prioridad que otro en el pool.

• Cuando tiene igual prioridad el planificador puede hacer las siguientes cosas:o Elegir uno y correrlo hasta que se bloquee o se

complete.o Usar time slicing y darles igual oportunidad a todos.

Page 41: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Poniendo prioridad de hilo

• Un hilo creado tendrá “la misma prioridad que el hilo que lo crea”

• Ejemplo: public class TestThreads { public static void main (String [] args) { MyThread t = new MyThread(); } }

En este código, t tiene la misma prioridad que el hilo main, ya que este lo creó.

• Tambien se pude poner la priorida con setPriority(): Thread t = new Thread( new FooRunnable() ); t.setPriority(8); t.start();

Page 42: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Los valores pueden ir del 1 al 10, aunque algunos JVM puede que vayan del 1 al 5, en tal caso, se hace una equivalencia de valores.

• Si es que pasa el segundo caso, y se declarará varios hilos con distintas prioridades cada uno, puede que algunos tengan prioridad 1.

• Aunque el default es 5, hay 3 constantes que definen el rango de prioridad:

Thread.MIN_PRIORITY (1) Thread.NORM_PRIORITY (5) Thread.MAX_PRIORITY (10)

Page 43: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Método yield()

• Entonces este método lo que hace es poner al hilo en ejecución de vuelta al estado runnable para que otro hilo con la misma prioridad corra.

• yield() promueve la toma de turno entre hilos de igual prioridad.

• Y otra vez, no hay garantía que escoja otro hilo y no el mismo hilo, una y otra vez.

• yield() nunca hará que el hilo se vaya al estado waiting/sleeping/ blocking.

Page 44: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Metodo join()

• Lo que dice este metodo es que si tenemos un hilo B, no puede hacer su trabajo hasta que el hilo A haya terminado(estado dead), o sea , el hilo B join al hilo A.

• Arroja InterruptedException en tiempo de ejecucion.• Si tenemos:

Thread t = new Thread(); t.start(); t.join();

o Toma al hilo corriendo y le hace join al hilo en t, es decir, lo pone al final de la ejecucion del hilo t, hasta que el hilo t haya terminado.

Page 45: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Se puede usar tambien el metodo sobrecargado que acepta un long que representa milisegundos, el cual es el tiempo maximo que tiene el hilo para terminar.

• Cuando acaba el tiempo, el hilo puesto en espera, deja de esperar y pasa a ser runnable otra vez.

• Ver ejemplo Hilos3.MyJoin.java

Page 46: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Hasta ahora se han visto 3 métodos que sacan del estado runnable a un hilo:o Sleep(): Garantiza que por un tiempo este en

sleep(aunque puede ser interrumpido antes de tiempo).o Yield(): No garantiza nada, solo poner de vuelta a un

hilo a esta runnable para que se pueda elegir otro de la misma prioridad.

o Join(): Garantiza parar al hilo corriendo actualmente hasta que el hilo que llama a join() termine de ejecutarse.

Page 47: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Otras escenarios para dejar estado runnable:o Terminar el metodo run()o Una llamada al metodo wait() de un objeto.o Un metodo no puede adquierir el bloqueo de un objeto

que esta a punto de correr.o Y cuando el planificador lo decida.

Page 48: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Sincronizando Código

• Se presenta el problema conocido como “condicion de carrera”, es cuando multiples hilos tratan de accesar al mismo recurso. Los datos pueden corromperse porque realizan la operación muy rapido antes que la operación (se supone que tiene que ser atomica) termina.

• Ver ejemplo Hilos4. AccountDanger.java

Page 49: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Prevención de condición de carrera

• Java nos permite evitar y prevenir que se de el problema de condición de carrera, lo que se tiene que hacer es:o Marcar el objeto o metodo como privateo Sincornizar el codigo que modificará las variables.

• Así las operaciones se hacen atómicas.• Ver ejemplo Hilos4.AccountDangerSincro.java

Page 50: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Sincronización y bloqueos

• Todo objeto en java tiene un bloqueo incorporado, cuando se llama a un método no estático sincronizado automáticamente llama al bloqueo de la instancia de la clase que se esta ejecutando.

• Se usa el nombre monito para el objeto del cual se obtiene el bloqueo.

• Técnicamente monitor y bloque son cosas distintas, pero aquí se lo va a tratar indiferente.

• Dado que hay un solo bloqueo por objeto, si un objeto obtiene el bloque, ningún otro podrá obtenerlo, hasta que el primero lo libere.

Page 51: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Esto significa que si se entra a un método synchronized, ningún otro entrará hasta que el bloqueo sea librado típicamente cuando salga del método.

• Usar la sincronización en casos necesarios, podría causar un deadlock si se lo usa incorrectamente, tener cuidado al usarlo.

• Si un hilo se va a sleep, sostiene el bloqueo, no lo libera.

• Un hilo puede obtener mas de un hilo, eso se da cuando se llama a dos métodos sincronizados de clases diferente.

Page 52: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Un hilo puede llamar a un método sincronizado dentro de otro método sincronizado de la misma clase, la JVM usa el mismo bloqueo.

• Se puede sincronizar un bloque de código en vez de un solo método, se lo puede hacer dentro del método.o Ejemplo:

public void doStuff() { System.out.println("not synchronized"); synchronized(this) { System.out.println("synchronized"); } }

Page 53: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Cuando se usa un bloque sincronizado, se le puede indicar que objeto usar para el bloqueo.

• Ejemplo: public synchronized void doStuff() { System.out.println("synchronized"); }

Es lo mismo que : public void doStuff() { synchronized(this) { System.out.println("synchronized"); } }

Page 54: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Sincronización de Métodos Estáticos

• Debemos saber que toda clase cargada en Java tiene su instancia de la clase java.lang.Class representando a esa clase, que nos va ser util para los bloques sincronizados.

• Para sincronizar un metodo estatico igual que un metodo no estatico,hay que poner la palabra synchronized.

• Ejemplo: public static synchronized int getCount() { return count; }

Page 55: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Si se lo quiere hacer con un bloque, se lo hace de la siguiente manera:

public static int getCount() { synchronized(MyClass.class) { return count; }

} O public static void classMethod() {

Class cl = Class.forName("MyClass"); synchronized (cl) { // do stuff }

}

Page 56: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• MyClass.class y Class.forName("MyClass"), devuelve un tipo java.lang.Class que es la instancia de Class que representa la clase llamada.

• Se llama literal de clase.• Esto no es objeto del examen.

Page 57: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Sincronizando un bloque de codigo

• Ver ejemplos de Hilos5:o Juez y Letras

Page 58: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Que pasa sin hilo no puede obtener el seguro de un objeto• Cuando un hilo entra a un método sincronizado y el

seguro ha sido tomado, se dice que el hilo esta bloqueado por el seguro del objeto.

• Lo que pasa aquí, es que el hilo se va a un pool en donde tiene que espera a que el objeto se libere.

• Pero no hay garantía de que a un hilo especifico le toque un turno.

Page 59: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Hay que prestar atencion que objeto es el que se usa para el bloqueo:o Si se usan métodos no estáticos sincronizados de una

misma clase, solo bloqueará hilos que usen la misma instancia, si se usan dos instancias diferentes, se obtendrá 2 seguros diferentes.

o SI se usan metodos estaticos sincronizados de la misma clase, bloqueara a todos los hilos que la llamen, puesto que usan un mismo seguro.

o Un metodo statico y uno no estatico JAMAS se bloqueran, puesto que el estatico usa el bloqueo de la instancia de Class, mientras que el no estatico usa el bloqueo de la instancia “this”, son dos seguros distintos.

Page 60: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Para cuando se usa bloques sincronizados, se tiene que ver que objeto se uso para el bloqueo, si dos hilos usan el mismo objeto, se bloquean en espero por ese objeto, pero si se usaron dos objetos diferentes, no. Osea, objetos sincronizados con el mismo objeto, se bloquearán, mientras que los que usaron distintos, no.

Page 61: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Cuando se necesita sincronizar???

• Para prevenir condicion de carrera• Asegurarse de que dos o ams hilos esten

cambiando el mismo dato al mismo tiempo.• Preocuparse cuando se trabaje con campos

estáticos o no estáticos, que contienen datos que pueden ser cambiados.

• Para campos no estaticos se usan metodos no estaticos sincronizados y asegurarse que los hilos usen la misma instancia.

• Con campos estaticos se usan metodos estaticos con la instancia de Class.

Page 62: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Casos:o Accesar a un campo estatico desde un metodo no estatico.

Si se usan diferentes instancias, no se bloquearan los hilos.o Accesar a un campo no estático a través de un método

estático (como parámetro) SI se usan un método estático y otro no estático para acceder,

las instancias que se usan son diferentes, una de Class y otra de this.

• Solucion:o Para campos estaticos, metodos estaticoso Para campos no estaticos, metodos no estaticos.

• EN TODOS LOS CASOS, SE HABLA DE METODOS SINCRONIZADOS.

Page 63: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Clases Thread-Safe

• Se dice que una clase es Thread-Safe cuando se han aplicado las reglas mencionadas antes o métodos mas complejos para la protección de datos en el trabajo con hilo.

• Algunas clases en java ya usan sincronización interna para que sean “Thread-Safe”, como StringBuffer.

• A pesar de esto, no es del todo seguro dejarles todo el trabajo de sincronización, aun con estas clases hay que tener cuidado.

Page 64: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Ver ejemplo Hilos6.NameList.javao Al hacer Collections.synchronizedList(), esto devuelve

una List con todos sus métodos sincronizados (size(),remove(),add(), todos).

o Puede que en alguna ejecucion salga : Thread t1 executes names.size(), which returns 1. Thread t2 executes names.size(), which returns 1. Thread t1 executes names.remove(0), which returns Ozymandias. Thread t2 executes names.remove(0), which throws an exception because the list is now empty.

o Esto es porque aunque todos los métodos están sincronizados, entre método y método no hay sincronización. Solución: Atomizar las operaciones que están involucradas,

en este caso puede ser el método.

Page 65: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• EL mensaje aquí es que a pesar de que el objeto que se usa sea Thread-safe, puede que se tenga que tomar otras medidas extras (syncronized).

Page 66: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Deadlock de Hilos

• Es cuando los hilos se bloquean entre esperando recursos que ya están siendo usados… (ya lo vimos en SO).

• Ver ejemplo Hilos6.DeadLockRisk.java• Aunque (dice en el libro), que a pesar de que hay

riesgo de deadlock, estos casos corren seguros en un 99.9%, gracias al trabajo del CPU.

• Y en este caso en particular, la forma de evitar un posible deadlock es invertir el orden del objeto usado en el bloque sincronizado en uno de los dos metodos.

Page 67: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Ademas para prevenir deadlock, hay tecnicas, metodos, estrategias para tomar seguros en un orden determinado que se pueden aplicar.

• Y como mensaje final si es que se cae en un deadlock, estás frito,

Page 68: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Interaccion entre hilos

• Esta seccion trata sobre la comunicación entre hilos, en el aspecto de decir cuando esperar por algo y cuando notificar que puede empezar a realizar alguna funcion.

• La forma en que se comunican es con los sgtes metodos:o wait()o notify()o notifyAll()

Page 69: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Puntos importantes a considerar para el examen:o LOS METODOS notify() Y wait(), SOLO PUEDEN SER

LLAMADOS DENTRO DE CONTEXTOS SINCRONIZADOS.

o NO SE PUEDE LLAMAR A LOS METODOS notify() Y wait() A MENOS QUE SE TENGA EL SEGURO DE ESE OBJETO.

• Ver ejemplo Hilos7.ThreadA.java• En tiempo de compilacion wait() arroja

InterruptedException.• Y en tiempo de ejecución arroja

IllegalMonitorStateException, si es que no se escogió el mismo objeto para la sincronización y el bloqueo.

Page 70: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

• Cuando se llama al metodo wait(), el hilo actual corriendo se pone en una lista de espera para poder seguir ejecutandi su codigo.

• Tambien existe el metodo sobrecagado wait(long ms), que abandona el estado la lista de espera despues del tiempo especificado, y vuleve a su ejecucion.

• Modificar ejemplo Hilos7.ThreadA.java

Page 71: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access
Page 72: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Usando notifyAll()

• Es para cuando varios hilos estan esperando.• Les dice a toda la lista de espera que sigan con la

ejecucion de su codigo.• Ver ejemplo Hilos7. Reader.java

Page 73: Capítulo 9: THREADS Carlos Oñate Bravo. THREADS Start New Threads lRecognize Thread States and Transitions Use Object Locking to Avoid Concurrent Access

Usando wait en un lazo