Escolar Documentos
Profissional Documentos
Cultura Documentos
Multithreading
Un procesador ejecuta las instrucciones
secuencialmente una despus de la otra se le llama un Execution Thread (Hilo de Ejecucin)
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)
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)
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:
Multithreading:Ventajas
Aplicaciones con mejor tiempo de respuesta
(an en mquinas con un solo CPU) procesadores simultneamente
No
(almacenar copia en memoria)
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
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(); }
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
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)
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
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); }
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) {
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() { }
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.
y en otra clase:
demo.counter = demo.counter + 1; //Evita el lock!
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; } }
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