Você está na página 1de 38

Multithreading y Java

Ing. Gerardo Horvilleur simpleJ Comunidad Java Sun Java Champion

Multithreading
Un procesador ejecuta las instrucciones
secuencialmente una despus de la otra se le llama un Execution Thread (Hilo de Ejecucin)

A esta ejecucin secuencial de instrucciones Multithreading es cuando se estn


ejecutando varios threads simultneamente

Multithreading: Un CPU
Si un procesador ejecuta las instrucciones Realmente no puede hacerlo, pero puede
simular que lo hace. secuencialmente una despus de la otra... Cmo le hace para ejecutar varios threads simultneamente?

Multithreading: Un CPU
Run Queue
T T T T Ready to Run T Quantum Timeout T I/O Request Sleep Lock T T

Waiting
T T T

CPU (running)

I/O Request Lock

Multithreading: Priorities
Run Queues
Priorities: Higher Lower Ready to Run T T T T T T T T T T I/O Request Sleep Lock Quantum Timeout T

Waiting
T T T

T T

CPU (running)

I/O Request Lock

Multithreading: MultiCPU
Run Queues
Priorities: Higher Lower T T T

Waiting
T T T

T T

T T T

T T T T

CPU (running)

CPU (running)

CPU (running)

Multithreading: OS
Sistemas Operativos con soporte para multithreading:

AIX Linux Mac OS X Solaris Windows


Pero cada uno tiene su propio API de threads!

Multithreading:Ventajas
Aplicaciones con mejor tiempo de respuesta
(an en mquinas con un solo CPU) procesadores simultneamente

Permite que una aplicacin utilice varios Mejor aprovechamiento de la computadora

Ejemplo: Web Server


Abrir Server Socket Esperar Conexin Pausa Pausa Pausa Leer Solicitud del Socket Leer Pgina de Disco Mandar Respuesta

Ejemplo: Web Server


Esperar Conexin Leer Solicitud del Socket

No
(almacenar copia en memoria)

Leer Pgina de Disco

Pgina en Memoria? S Mandar Respuesta

Ejemplo: Web Server


Esperar Conexin Crear thread para atender solicitud Atender Solicitud Atender Solicitud

Atender Solicitud Atender Solicitud

Ejemplo: Web Server


Esperar Conexin Poner en la Cola

Thread Pool
T T

T T T

T T T T

T T

T T

Java y Multithreading
Java cuenta con soporte para threads en el
lenguaje y la JVM

Mismo API en cualquier sistema operativo


(hasta los mismos ejecutables!) opcional:

En muchos casos usar threads no es Swing Servlets y JSP

Java Threads
Para manipular threads desde Java se emplea
la clase Thread
new Thread();

Thread

Runnable
Una manera de decirle que hacer a un
public interface Runnable { void run(); }

Thread es por medio de una clase que implemente la interfaz Runnable

Runnable
public class HazAlgo implements Runnable { public void run() { while (true) System.out.println(algo); } } new Thread(new HazAlgo());

HazAlgo Thread
T

Start
Para iniciar la ejecucin de un Thread se
emplea el mtodo start()
new Thread(new HazAlgo()).start()

HazAlgo Thread
T

Demo1
public class Demo1 implements Runnable { private int delay; public Demo1(int d) delay = d; } public void run() { while (true) { System.out.println(delay); try { Thread.sleep(delay * 1000); } catch (InterruptedException e) { break; } } }

Demo1 (cont.)
public static void main(String[] args) { for (int i = 0; i <= 5; i++) new Thread(new Demo1(i)).start(); } }

Join
Se puede esperar a que un thread termine
de ejecutarse por medio del mtodo join()
Thread t = new Thread(new HazAlgo()); t.start(); t.join(); //esperar a que termine

Demo2
public class Demo2 implements Runnable { private int counter; public void incrCounter() { counter = counter + 1; } public int getCounter() { return counter; } public void run() { for (int i = 0; i < 1000000; i++) incrCounter(); }

Demo2 (cont.)
public static void main(String[] args) throws InterruptedException { Demo2 demo2 = new Demo2(); Thread[] threads = new Thread[5]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(demo2); threads[i].start(); } for (int i = 0; i < threads.length; i++) threads[i].join(); System.out.println(demo2.getCounter()); } }

Accesos no controlados
Thread #1 Lee valor Incrementa valor Graba valor Lee valor Lee valor Incrementa valor Graba valor Thread #2

Incrementa valor Graba valor

Multiples Procesadores
CPU #1 Cache
Copia del valor

CPU #2 Cache
Copia del valor

Memoria
Valor

El problema es peor!

Locks (candados)
Cada objeto tiene un lock Slo un thread puede ser dueo de un
requiere adquirir un lock lock en un momento dado (un mismo thread puede ser dueo de varios locks)

El modicador synchronized indica cuando se Con synchronized tambin se garantiza la


sincrona en las jerarquas de memorias (caches)

Demo3
El modicador synchronized indica que se Si otro thread tiene el lock entonces se
public synchronized void incrCounter() { counter = counter + 1; }

debe adquirir el lock al entrar al mtodo y liberarlo al salir del mtodo detiene la ejecucin de este thread hasta que el otro lo libere

Cuidado!
El uso correcto de threads no implica

simplemente ponerle synchronized a todos los mtodos

Hay que entender lo que uno est haciendo

Demo4
public class Demo4 implements Runnable { private int counter; public synchronized int getCounter() { return counter; } public synchronized void setCounter(int v) { counter = v; } public void run() { for (int i = 0; i < 10000; i++) setCounter(getCounter() + 1); }

Entre el llamado a getCounter() y el llamado a setCounter() se libera el lock!

Synchronized statement
En ciertas ocasiones nos gustara obtener un
lock nicamente en una regin crtica de un mtodo (para permitir mayor concurrencia) synchronized statement
synchronized (expr) {

En estos casos se puede emplear un Sintaxis:


}

statements...

Synchronized Statement
El resultado de evaluar expr debe ser una
una manera sencilla de escribir un synchronized statement sobre el objeto actual Esto:
public synchronized void metodo() { }

referencia a un objeto (sobre el cual se va a adquirir el lock)

El modicador synchronized es simplemente

es equivalente a:
public void metodo() { synchronized (this) { } }

Demo5
public class Demo5 implements Runnable { int counter; public int getCounter() { return counter; } public void setCounter(int v) { counter = v; } public void run() { for (int i = 0; i < 10000; i++) synchronized (this) { setCounter(getCounter() + 1); } } }

Demo6
public class Demo6 implements Runnable { private Object obj1; private Object obj2; public Demo6(Object o1, Object o2) { obj1 = o1; obj2 = o2; } public void run() { for (int i = 0; i < 1000; i++) { synchronized (obj1) { synchronized (obj2) { System.out.println(i); } } } }

Demo6 (cont.)
public static void main(String[] args) { Object o1 = new Object(); Object o2 = new Object(); new Thread(new Demo6(o1, o2)).start(); new Thread(new Demo6(o2, o1)).start(); } }

Hay un deadlock! Un thread obtiene el lock sobre o1 y despus trata de obtener el lock sobre o2, pero el otro thread ya tiene ese lock y ahora quiere el lock que tiene el primer thread... Ctrl-\ para ver los threads y locks (Unix)

Cuidado!
Slo el cdigo dentro de un synchronized
est protegido por un lock... Los otros mtodos ignoran el lock.

Cuidado con variables public o protected


public int counter; public synchronized void incrCounter() { counter = counter + 1; }

y en otra clase:
demo.counter = demo.counter + 1; //Evita el lock!

Pertenecen a la clase y no a las instancias


public class Ejemplo { private static int counter; public synchronized void incrCounter() { counter = counter + 1; }

Variables static

Ejemplo
(clase) counter

Ejemplo
(instancia #1)

Ejemplo
(instancia #2)

Variables static
Dos posibles soluciones:
public static synchronized void incrCounter() { counter = counter + 1; }

o
public synchronized void incrCounter() { synchronized (Ejemplo.class) { counter = counter + 1; } }

Hay mucho ms!


Interrupcin de threads: interrupt, interrupted,
isInterrupted

Prioridades: setPriority, getPriority Coordinacin entre threads: wait, notify,


notifyAll

Background threads (daemons): setDaemon Y todava mucho ms...

Para saber ms
The Java Programming Language The Java Language Specication
Doug Lea Ken Arnold, James Gosling & David Holmes James Gosling, Bill Joy, Guy Steel & Gilad Bracha

Concurrent Programming in Java

Você também pode gostar