dit 
UPM 
Programación 
concurrente 
— 
Sincronización 
condicional 
Juan 
Antonio 
de 
la 
Puente 
<jpuente@dit.upm.es> 
...
Referencias 
• ScoB 
Oaks 
& 
Henry 
Wong 
Java 
Threads 
O'Reilly 
Media; 
3rd 
ed 
(2004) 
! 
•Kathy 
Sierra 
& 
Bert 
B...
Sincronización 
condicional
Sincronización 
condicional 
• A 
veces 
una 
hebra 
9ene 
que 
esperar 
hasta 
que 
se 
cumpla 
una 
determinada 
condici...
Ejemplo: 
ges9ón 
de 
un 
estacionamiento 
• Las 
hebras 
de 
las 
clase 
Sensor 
avisan 
cuando 
entra 
o 
sale 
un 
coch...
Sincronización 
• No 
deben 
entrar 
coches 
si 
el 
estacionamiento 
está 
lleno 
‣ no 
se 
puede 
entrar 
si 
n 
>= 
cap...
Ejemplo: 
productor 
y 
consumidor 
• Una 
hebra 
produce 
elementos 
de 
un 
cierto 
9po 
• Otra 
los 
consume 
• Cada 
u...
Sincronización 
• No 
se 
pueden 
extraer 
datos 
si 
el 
buffer 
Programación 
concurrente 
— 
Sincronización 
condiciona...
Esperar 
y 
avisar
Espera 
condicional 
• El 
método 
wait() 
suspende 
la 
ejecución 
de 
la 
hebra 
que 
lo 
invoca 
• Se 
usa 
para 
esper...
Aviso 
de 
condición 
• El 
método notify() 
reanuda 
la 
ejecución 
de 
una 
hebra 
que 
esté 
suspendida 
por 
haber 
he...
Aviso 
general 
• El 
método notifyAll() 
reanuda 
la 
ejecución 
de 
todas 
las 
hebras 
que 
esté 
suspendidas 
por 
hab...
Colas 
de 
espera 
y 
de 
entrada 
adquirir 
el 
cerrojo wait 
© 
2014 
Programación 
concurrente 
— 
Sincronización 
cond...
no9fy 
vs 
no9fyAll 
• Siempre 
que 
varias 
hebras 
puedan 
estar 
esperando 
condiciones 
dis9ntas 
hay 
que 
usar 
Prog...
Ejemplo: 
estacionamiento
Monitor 
con 
condiciones 
public class Parking { 
private final int capacidad; // número de coches que caben 
private int...
Productor 
y 
consumidor
Ejemplo: 
buffer 
public class Buffer<E> { 
! 
private E almacen; 
private boolean lleno = false; 
! 
public synchronized ...
Ejemplo: 
productor 
public class Productor<E> implements Runnable { 
! 
private Buffer<E> b; 
! 
public Productor(Buffer<...
Ejemplo: 
consumidor 
public class Consumidor<E> implements Runnable { 
! 
private Buffer<E> b; 
! 
public Consumidor(Buff...
Resumen
Resumen 
• La 
sincronización 
condicional 
se 
realiza 
en 
Java 
con 
los 
métodos 
wait() 
y 
no9fy() 
/ 
no9fyAll() 
‣...
Próxima SlideShare
Cargando en…5
×

Programación concurrente: sincronización condicional

1.288 visualizaciones

Publicado el

Sincronización condicional con monitores. Esperar y avisar: wait y notify/notifyAll en Java.

Publicado en: Software
0 comentarios
1 recomendación
Estadísticas
Notas
  • Sé el primero en comentar

Sin descargas
Visualizaciones
Visualizaciones totales
1.288
En SlideShare
0
De insertados
0
Número de insertados
9
Acciones
Compartido
0
Descargas
14
Comentarios
0
Recomendaciones
1
Insertados 0
No insertados

No hay notas en la diapositiva.

Programación concurrente: sincronización condicional

  1. 1. dit UPM Programación concurrente — Sincronización condicional Juan Antonio de la Puente <jpuente@dit.upm.es> Algunos derechos reservados. Este documento se distribuye bajo licencia Crea9ve Commons Reconocimiento-­‐NoComercial-­‐Compar9rIgual 3.0 Unported. hBp://crea9vecommons.org/licenses/by-­‐nc-­‐sa/3.0/deed.es 20141008
  2. 2. Referencias • ScoB Oaks & Henry Wong Java Threads O'Reilly Media; 3rd ed (2004) ! •Kathy Sierra & Bert Bates Head First Java, ch. 15 O'Reilly Media; 2nd ed (2005) Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente 2
  3. 3. Sincronización condicional
  4. 4. Sincronización condicional • A veces una hebra 9ene que esperar hasta que se cumpla una determinada condición ‣ suspende su ejecución hasta que esto ocurra • Otra hebra hace que se cumpla la condición ‣ avisa al que estaba esperando ‣ éste puede reanudar su ejecución • Este 9po de sincronización se llama sincronización condicional ‣ sincronización: el avance de una hebra depende de lo que haga otra hebra Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente 4
  5. 5. Ejemplo: ges9ón de un estacionamiento • Las hebras de las clase Sensor avisan cuando entra o sale un coche Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente 5 «monitor»! Parking! - n : natural! + entra! + sale! + ocupado: natural «thread»! Sensor! ! - acceso, id «thread»! Supervisor
  6. 6. Sincronización • No deben entrar coches si el estacionamiento está lleno ‣ no se puede entrar si n >= capacidad ‣ si un sensor llama a entra cuando n >= capacidad, debe suspender su ejecución hasta que haya si9o -­‐ está implícito que en ese caso no se abre la barrera hasta que se pueda con9nuar Programación concurrente — Exclusión mutua © 2014 Juan A. de la Puente 6
  7. 7. Ejemplo: productor y consumidor • Una hebra produce elementos de un cierto 9po • Otra los consume • Cada una avanza con un ritmo diferente • Se usa un almacenamiento intermedio (buffer) ‣ el productor los va poniendo en el buffer según los produce ‣ el consumidor los saca del buffer cuando los necesita Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente 7 «thread»! Productor «thread»! Consumidor «monitor»! Buffer! + envia! + recibe
  8. 8. Sincronización • No se pueden extraer datos si el buffer Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente está vacío ‣ si cuando el consumidor invoca recibe no hay datos en el buffer, debe suspender su ejecución hasta que los haya ‣ es el productor el que los pone • No se pueden añadir datos si el buffer está lleno ‣ si cuando el productor invoca envía el buffer está lleno, debe suspender su ejecución hasta que haya si9o ‣ es el consumidor el que hace si9o al extraer datos 8
  9. 9. Esperar y avisar
  10. 10. Espera condicional • El método wait() suspende la ejecución de la hebra que lo invoca • Se usa para esperar una condición while (!condición) wait(); ‣ ¡siempre en un bucle! • Sólo se puede invocar dentro de un método sincronizado ‣ o de un bloque sincronizado • Se libera el cerrojo del objeto atómicamente ‣ al mismo 9empo que se hace wait() • Puede lanzar una excepción InterruptedExcep;on ‣ usar manejador o propagar Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente 10
  11. 11. Aviso de condición • El método notify() reanuda la ejecución de una hebra que esté suspendida por haber hecho Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente wait() • Se usa para avisar de que se cumple una condición // cambiar el estado de alguna condición notify(); • Una hebra avisa a otra • Sólo se puede invocar dentro de un método sincronizado ‣ o de un bloque sincronizado • No se libera el cerrojo del objeto hasta que termina el método o sentencia sincronizada ‣ la hebra que se reanuda intenta adquirir el cerrojo para con9nuar ‣ puede tener que compe9r con otras hebras 11
  12. 12. Aviso general • El método notifyAll() reanuda la ejecución de todas las hebras que esté suspendidas por haber hecho wait() en el mismo objeto • El cerrojo del objeto se libera cuando termina el método o sentencia sincronizada ‣ todas las hebras que se reanudan compiten para adquirir el cerrojo y poder con9nuar • Con notify() no se sabe qué hebra se reanuda entre las que estaban suspendidas • Con notifyAll() se reanudan todas y comprueban otra vez la condición Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente 12
  13. 13. Colas de espera y de entrada adquirir el cerrojo wait © 2014 Programación concurrente — Sincronización condicional Juan A. de la Puente 13 cerrojo cola de entrada cola de espera
  14. 14. no9fy vs no9fyAll • Siempre que varias hebras puedan estar esperando condiciones dis9ntas hay que usar Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente notifyAll • Sólo conviene hacer notify si ‣ todas las hebras esperan la misma condición ‣ sólo una hebra puede avanzar cuando se cumple la condición • En caso de duda, usar notifyAll 14
  15. 15. Ejemplo: estacionamiento
  16. 16. Monitor con condiciones public class Parking { private final int capacidad; // número de coches que caben private int n = 0; // número de coches que hay ! // constructor public Parking (int capacidad) { this.capacidad = capacidad; } // entra un coche por una de las puertas public synchronized void entra (String puerta) { while (n >= capacidad) wait(); n++; } // sale un coche por una de las puertas public synchronized void sale (String puerta) { n—; notifyAll(); } // consulta public synchronized int ocupado() { return n; } } © 2014 Programación concurrente — Exclusión mutua Juan A. de la Puente 16
  17. 17. Productor y consumidor
  18. 18. Ejemplo: buffer public class Buffer<E> { ! private E almacen; private boolean lleno = false; ! public synchronized void enviar(E dato) throws InterruptedException { while (lleno) wait(); // espera que haya sitio almacen = dato; lleno = true; notifyAll(); // avisa de que hay un valor } ! public synchronized E recibir() throws InterruptedException { E dato = null; while (!lleno) wait(); // espera que haya un valor dato = almacen; lleno = false; notifyAll(); // avisa de que hay sitio return dato; } } © 2014 Programación concurrente — Sincronización condicional Juan A. de la Puente 18
  19. 19. Ejemplo: productor public class Productor<E> implements Runnable { ! private Buffer<E> b; ! public Productor(Buffer<E> b) { this.b = b; } ! public void run() { while (true) { E x = …; // producir x b.enviar(x); } } } ! // la sincronización está oculta en el buffer © 2014 Programación concurrente — Sincronización condicional Juan A. de la Puente 19
  20. 20. Ejemplo: consumidor public class Consumidor<E> implements Runnable { ! private Buffer<E> b; ! public Consumidor(Buffer<E> b) { this.b = b; } ! public void run() { while (true) { E x = b.recibir(); … // consumir x } } } ! // la sincronización está oculta en el buffer © 2014 Programación concurrente — Sincronización condicional Juan A. de la Puente 20
  21. 21. Resumen
  22. 22. Resumen • La sincronización condicional se realiza en Java con los métodos wait() y no9fy() / no9fyAll() ‣ sólo se pueden usar en métodos/bloques sincronizados ‣ wait() suspende la hebra desde donde se invoca ‣ no9fy() reanuda una hebra suspendida ‣ no9fyAll() reanuda todas las hebras suspendidas ! • Hay que hacer wait() siempre en un bucle while ‣ para comprobar otra vez la condición de espera cuando despierta while (!condición) wait(); Programación concurrente — Sincronización condicional © 2014 Juan A. de la Puente 22

×