Programaci - PowerPoint PPT Presentation

About This Presentation
Title:

Programaci

Description:

private boolean escribiendo = false; public synchronized void OpenL(int i) throws Exception ... private boolean escribiendo = false; private int nEscritores = 0; ... – PowerPoint PPT presentation

Number of Views:157
Avg rating:3.0/5.0
Slides: 63
Provided by: mdelmarg
Category:

less

Transcript and Presenter's Notes

Title: Programaci


1
Programación Concurrente en Java
  • Métodos sincronizados
  • Monitores y condiciones

Programación Concurrente ETSI Informática-UMA
M.M. Gallardo
2
Métodos Sincronizados
  • Cada objeto Java tiene asociado un lock
    (cerrojo).
  • La palabra synchronized puede utilizarse para
    señalar aquellos métodos del objeto que deben
    ejecutarse en exclusión mutua.
  • Antes de ejecutar un método sincronizado hay que
    competir para conseguir el lock del objeto al que
    pertenece.

3
Ejemplo Problema de los jardines
  • public class Cont
  • private int c 0
  • public synchronized void inc(int i)
  • c
  • public synchronized int valor()
  • return c

La ejecución de inc se realiza en exclusión mutua
4
Ejemplo Problema de los jardines
  • public class puerta implements Runnable
  • Cont c
  • public jardin(Cont c)this.c c
  • public void run()
  • for (int i 0 ilt20 i)
  • c.inc(1)

La ejecución de inc se realiza en exclusión mutua
5
Ejemplo Problema de los jardines
  • public class UsaJardines
  • public static void main(String args)
  • final int N 10
  • Cont c new Cont()
  • puerta p new puertaN
  • for (int i 0 ilt N i) pi new
    puerta(c)
  • Thread ph new ThreadN
  • for (int i 0 ilt N i) phi new
    Thread(pi)
  • for (int i 0 ilt N i) phi.start()
  • for (int i 0 ilt N i)
  • tryphi.join()
  • catch (InterruptedException e)
  • System.out.println(c.valor())

Todas las hebras compiten
6
Mecanismo de entrada/salida al Monitor
7
  • Java no asigna ninguna estructura concreta a las
    hebras que están en el conjunto de entrada. La
    implementación podría usar
  • Una FIFO
  • Una LIFO
  • Una FIFO basada en prioridades

8
Condiciones de sincronización
  • Cuando una hebra que tiene el lock de un objeto
    y debe suspenderse debido a alguna condición de
    sincronización, se introduce en el conjunto de
    espera del objeto, llamando al método
  • void wait()
  • Cuando una hebra ejecuta wait()
  • - Libera el lock del objeto sincronizado
  • - Se bloquea en el conjunto de espera

9
Mecanismo de entrada/salida revisado
10
Disciplina del Monitor
  • Los métodos void notify(), void notifiyAll()
    despiertan a una/todas las hebras del conjunto de
    espera.
  • Java utiliza la disciplina notify-and-continue,
    es decir, la hebra que hace notify continúa con
    el lock del monitor. Por lo tanto, la hebra que
    espera debe ejecutar un código del tipo
  • while (!condicion)
  • try wait()
  • catch (Exception e)

11
Métodos sincronizadosProductor/Consumidor
  • public class Buffer
  • private int b
  • private int tam
  • private int i0
  • private int j0
  • private int numDatos 0
  • public Buffer(int t)
  • tam t
  • b new inttam
  • ...........

12
Métodos sincronizadosProductor/Consumidor
  • .....
  • public synchronized void poner(int d) throws
    InterruptedException
  • while (numDatos tam) wait()
  • bi d
  • i (i 1) tam
  • numDatos
  • notify()
  • public synchronized int extraer() throws
    InterruptedException
  • while (numDatos 0) wait()
  • int aux j j (j 1) tam
  • numDatos--
  • notify()
  • return baux

mientras el buffer está lleno/vacío esperar
13
Métodos sincronizadosProductor/Consumidor
  • .....
  • public synchronized void poner(int d) throws
    InterruptedException
  • while (numDatos tam) wait()
  • bi d
  • i (i 1) tam
  • numDatos
  • notify()
  • public synchronized int extraer() throws
    InterruptedException
  • while (numDatos 0) wait()
  • int aux j j (j 1) tam
  • numDatos--
  • notify()
  • return baux

Cambia el estado del buffer y aviso a la otra
hebra, por si acaso
14
Métodos sincronizados conjunto de espera único
  • Cuando se utilizan métodos sincronizados hay sólo
    un conjunto de espera, en el que pueden estar
    suspendidas hebras que esperan que diferentes
    condiciones de sincronización sean ciertas.
  • Cuando una hebra ejecuta notify, puede ser que no
    despierte a la hebra adecuada, por lo que habrá
    que programar un despertado en cascada o utilizar
    el método notifyAll().

15
Múltiples productores y consumidores
Condiciones de sincronización Hay varios procesos
productores y consumidores. Todos los procesos
utilizan el buffer en exclusión mutua. Un
productor no puede escribir hasta que no hay
sitio en el buffer. Los consumidores leen todos
los datos producidos, En el mismo orden. Si el
buffer está vacío esperan.
16
Múltiples productores y consumidores
-suponiendo 1 productor y 3 consumidores
numDatos 3
j
b
A
Z
M
k
f
2
3
0
0
1
0
0
0
flect
c
2
3
5
Índice para cada consumidor
17
Múltiples productores y consumidores
-si el consumidor 2 consume
numDatos 3
j
b
A
Z
M
k
f
2
3
0
0
1
flect
0
0
0
fcons
c
2
3
4
3
2
0
Índice para cada consumidor
Ya no puede consumir más
18
Múltiples productores y consumidores
-si el consumidor 0 consume
numDatos 2
j
b
A
Z
M
k
f
0
2
3
0
0
flect
0
0
0
fcons
c
3
3
4
2
2
0
Índice para cada consumidor
Deja un hueco libre para el productor
19
Múltiples productores y consumidores
-si el productor produce
numDatos 3
j
b
H
A
Z
M
k
f
0
2
3
0
0
flect
3
0
0
fcons
c
3
3
4
3
3
1
Índice para cada consumidor
Indica a todos que pueden Consumir un dato más
20
Múltiples productores y consumidores
  • package multProdCons
  • public class Buffer
  • private int b // buffer
  • private int c // indice de cada consumidor
  • private int fdatos // para cada consumidor,
    los datos que le quedan por leer
  • private int flect // para cada dato, las
    lecturas que le quedan
  • private int tam
  • private int i0
  • private int j0
  • private int numDatos 0
  • private int nlectores 0
  • .................

21
Múltiples productores y consumidores
  • public Buffer(int t,int nlectores)
  • tam t
  • b new inttam
  • c new inttam
  • for (int i0ilttami) ci 0
  • this.nlectores nlectores
  • fdatos new intnlectores
  • for (int i0iltnlectoresi)
  • fdatosi 0
  • flect new inttam
  • for (int i 0 i lt tam i)
  • flecti 0
  • System.out.println("buffer inicializado")

22
Múltiples productores y consumidores
  • public synchronized void poner(int id,int d)
    throws InterruptedException
  • while (numDatos tam) notify() wait()
  • bi d
  • for (int c 0 c lt nlectores c)
    fdatosc
  • flecti nlectores
  • i (i 1) tam
  • numDatos
  • notify()

En la sala de espera hay procesos productores y
consumidores. Cuando se despierta una hebra,
puede ser que tenga que seguir esperando....
Desperado en cascada
23
Múltiples productores y consumidores
  • public synchronized int extraer(int id) throws
    InterruptedException
  • while (fdatosid 0) notify() wait()
  • int aux cid
  • fdatosid--
  • flectcid--
  • if (flectcid 0) numDatos-- notify()
  • cid (cid 1) tam
  • return baux

Como en el caso de los productores
Desperado en cascada
24
Múltiples productores y consumidores
  • public class Consumidor implements Runnable
  • Buffer b
  • int id
  • public Consumidor(Buffer b, int id)
  • this.b b
  • this.id id
  • public void run()
  • int d 0
  • System.out.println("comienza consumidor")
  • for (int i0ilt10i)
  • tryd b.extraer(id)
  • catch (Exception e)
  • System.out.println("Consumidor " d)

25
Múltiples productores y consumidores
  • public class Productor implements Runnable
  • Buffer b
  • int id
  • public Productor(Buffer b,int id)
  • this.b b
  • this.id id
  • public void run()
  • System.out.println("comienza productor")
  • for (int i 0 ilt10 i)
  • try b.poner(id,i)
  • catch (Exception e)
  • System.out.println("Productor "i)

26
Múltiples productores y consumidores
  • public class UsaProdCons
  • public static void main(String args)
  • final int numCons 5
  • Buffer b new Buffer(5,numCons)
  • Productor p new Productor(b,1)
  • Consumidor c new ConsumidornumCons
  • for (int i 0 iltnumCons i) ci new
    Consumidor(b,i)
  • System.out.println("comienza el programa")
  • Thread ph new Thread(p)
  • Thread ch new ThreadnumCons
  • for (int i 0 iltnumCons i) chi new
    Thread(ci)
  • for (int i 0 iltnumCons i) chi.start()
  • ph.start()

27
Múltiples productores y consumidores con notifyAll
  • public synchronized void poner(int id,int d)
    throws InterruptedException
  • System.out.println("productor " id "quiere
    poner "d)
  • while (numDatos tam) wait()
  • System.out.println("productor " id "
    escribe en el buffer")
  • bi d
  • for (int c 0 c lt nlectores c)
    fdatosc
  • flecti nlectores
  • i (i 1) tam
  • numDatos
  • notifyAll()

Hay un nuevo dato y aviso a todos
28
Lectores/Escritores (v. injusta)
  • public class ControlBD
  • private int nLectores 0
  • private boolean escribiendo false
  • public synchronized void OpenL(int i) throws
    Exception
  • while (escribiendo) wait()
  • nLectores
  • System.out.println("Entra lector "i)
  • public synchronized void OpenE(int i) throws
    Exception
  • while (escribiendo (nLectores gt 0)) wait()
  • escribiendo true
  • System.out.println("Entra escritor "i)
  • ......

29
Lectores/Escritores (v. injusta)
  • public synchronized void CloseL(int i) throws
    Exception
  • nLectores--
  • if (nLectores 0) notifyAll()
  • System.out.println("Sale lector "i)
  • public synchronized void CloseE(int i) throws
    Exception
  • escribiendo false
  • notifyAll()
  • System.out.println("Sale escritor "i)

30
Lectores/Escritores (v. injusta)
  • public class Escritor implements Runnable
  • int miId
  • ControlBD c
  • public Escritor(int id,ControlBD c)
  • miId id this.c c
  • public void run()
  • for (int i 0 i lt 10 i)
  • try c.OpenE(miId)
  • Thread.sleep(1)
  • c.CloseE(miId)
  • catch (Exception e)

31
Lectores/Escritores (v. injusta)
  • public class Lector implements Runnable
  • int miId
  • ControlBD c
  • public Lector(int id,ControlBD c)
  • miId idthis.c c
  • public void run()
  • for (int i 0 i lt 10 i)
  • try c.OpenL(miId)
  • Thread.sleep(1)
  • c.CloseL(miId)
  • catch (Exception e)

32
Lectores/Escritores
  • El tener solo una cola de espera puede ser
    ineficiente si despertamos a procesos que no
    pueden continuar su ejecución porque todavía no
    se satisface la condición por la que esperan.

33
Lectores/Escritores (v. justa)
  • public class ControlBD
  • private int nLectores 0
  • private boolean escribiendo false
  • private int nEscritores 0
  • public synchronized void OpenL(int i) throws
    Exception
  • while (escribiendo (nEscritores gt 0))
  • System.out.println("Lector quiere entrar "i)
  • wait()
  • nLectores
  • ..............

34
Lectores/Escritores (v. justa)
  • public synchronized void OpenE(int i) throws
    Exception
  • nEscritores
  • while (escribiendo (nLectores gt 0))
  • System.out.println("Escritor quiere entrar
    "i)
  • wait()
  • escribiendo true

35
Lectores/Escritores (v. justa)
  • public synchronized void CloseL(int i) throws
    Exception
  • nLectores--
  • if (nLectores 0) notifyAll()
  • public synchronized void CloseE(int i) throws
    Exception
  • nEscritores--
  • escribiendo false
  • notifyAll()

Despierta a todos
36
Lectores/Escritores (v. justa)
  • public synchronized void CloseL(int i) throws
    Exception
  • nLectores--
  • if (nLectores 0) notifyAll()
  • public synchronized void CloseE(int i) throws
    Exception
  • nEscritores--
  • escribiendo false
  • notifyAll()

Despierta a todos
37
Lectores/Escritores (v. justa)
  • comienza Lectores/Escritores
  • Escritor quiere entrar 0
  • Escritor quiere entrar 1
  • Lector quiere entrar 0
  • Lector quiere entrar 1
  • Lector quiere entrar 2
  • Lector quiere entrar 3
  • Lector quiere entrar 4
  • Lector quiere entrar 5
  • Lector quiere entrar 6
  • Lector quiere entrar 7
  • Lector quiere entrar 8
  • Lector quiere entrar 9
  • Lector quiere entrar 10
  • Lector quiere entrar 11
  • Lector quiere entrar 12
  • Lector quiere entrar 13
  • Escritor quiere entrar 1
  • Lector quiere entrar 0

Hasta 350 intentos fallidos para 15 Lectores y
2 Escritores
38
Llamadas anidadas a métodos sincronizados
  • Para que h ejecute e.p(), debe obtener el lock de
    e

Ejemplo e ---
e.p()
39
Llamadas anidadas a métodos sincronizados
Ejemplo2 e1 ....
Ejemplo e ---
e.p()
e1.p()
Para que e ejecute e1.p() debe obtener el lock de
e1
40
Llamadas anidadas a métodos sincronizados
Ejemplo2 e1 ....
Ejemplo e ---
e.p()
e1.p()
41
Llamadas anidadas a métodos sincronizados
Ejemplo2 e1 ....
Ejemplo e ---
e.p()
e1.p()
Si se ejecuta wait(), se libera el lock de
e1, pero se mantiene el de e, lo que puede
producir bloqueos
42
Productor/Consumidor con condiciones y bloqueo
  • public class Condition
  • public synchronized void delay()
  • trywait() // suspende a la hebra que lo
    ejecuta
  • catch (Exception e)
  • public synchronized void resume()
  • trynotify() // despierta una hebra suspendida
  • catch (Exception e)

43
Productor/Consumidor con condiciones y bloqueo
  • public class Buffer
  • private int b
  • private int tam
  • private int i0
  • private int j0
  • private int numDatos 0
  • private final Condition nolleno new
    Condition()
  • private final Condition novacio new
    Condition()
  • public Buffer(int t)
  • tam t
  • b new inttam
  • .......

44
Productor/Consumidor con condiciones y bloqueo
  • public synchronized void poner(int d) throws
    InterruptedException
  • while (numDatos tam) nolleno.delay()
  • bi d
  • i (i 1) tam
  • numDatos
  • novacio.resume()
  • public synchronized int extraer() throws
    InterruptedException
  • while (numDatos 0) novacio.delay()
  • int aux j
  • j (j 1) tam
  • numDatos--
  • nolleno.resume()
  • return baux

Bloquea a la hebra Buffer
Bloquea a la hebra Buffer
45
Locks
  • Los métodos/instrucciones synchronized modelan el
    acceso exclusivo a lock de un monitor implícito
    asociado a un objeto, típicamente un recurso
    compartido por varias hebras.
  • Sin embargo, cuando una hebra necesita usar más
    de un recurso, debe liberar los locks de los
    recursos en orden inverso a como se han obtenido,
    lo que en ocasiones puede no ser adecuado
  • ....
  • A.acquire()
  • B.acquire()
  • C.acquire()
  • A.release()
  • D.acquire()
  • B.release() ......

46
Locks
  • public class ReentrantLock
  • ReentrantLock l new ReentrantLock()
  • Un Lock para la exclusión mutua con la misma
    semántica y comportamiento que el lock implícito
    tipo monitor de los métodos e instrucciones
    sincronizadas (synchronized), pero con más
    posibilidades.

47
Locks el problema de los jardines
Implementación de la interfaz lock
  • public class Cont
  • Lock l new ReentrantLock()
  • private int c 0
  • public void inc(int i)
  • l.lock()
  • try
  • c
  • finally
  • l.unlock()

Pido el lock
Devuelvo el lock
48
Locks el problema de los jardines
  • public int valor()
  • l.lock()
  • try
  • return c
  • finally
  • l.unlock()

Pido el lock
Devuelvo el lock
La cláusula try/finally es necesaria para
devolver el lock después de ejecutar return
49
Locks condiciones
Para modelar las condiciones de sincronización
usamos la Interfaz Condition.
  • public interface Condition
  • Las condiciones clasifican los métodos del
    monitor (wait, notify and notifyAll) en distintos
    objetos de forma que es posible tener múltiples
    conjuntos de espera por objeto, asociados a
    locks.
  • Lock l new ReentrantLock()
  • Condition c1 l.newCondition()
  • Condition c2 l.newCondition()

Las condiciones se asocian a locks y pueden
definirse tantas como sea necesario
50
Locks condiciones
  • Métodos
  • void await() throws InterruptedException
  • Suspende a la hebra en la condición
    correspondiente
  • void signal()
  • Despierta una de las hebras que espera. La hebra
    tiene que conseguir el lock correspondiente antes
    de continuar su ejecución.
  • (disciplina signal-and-continue)
  • void signalAll()
  • Desperta a todas las hebras que esperan. Cada
    hebra tiene que conseguir el lock correspondiente
    antes de continuar su ejecución.
  • (disciplina signal-and-continue)

51
Locks condiciones
  • Lock l new ReentrantLock()
  • Condition c1 l.newCondition()
  • Condition c2 l.newCondition()
  • l.lock()
  • try
  • while (!condicion1) c1.await() // mientras
    !condicion1 espera en c1
  • // condicion1 se satisface
  • // cambia el estado del objeto y condicion2 es
    cierta
  • c2.signal() // despertar una hebra que espera
  • finally
  • l.unlock()

52
Productor/Consumidor
  • package condicion
  • import java.util.concurrent.locks.
  • public class Buffer
  • private int b
  • private int tam
  • private int i0
  • private int j0
  • private int numDatos 0
  • private final ReentrantLock lockBuffer new
    ReentrantLock()
  • private final Condition nolleno
    lockBuffer.newCondition()
  • private final Condition novacio
    lockBuffer.newCondition()
  • public Buffer(int t)
  • tam t
  • b new inttam
  • .........

53
Productor/Consumidor
  • public void poner(int d) throws
    InterruptedException
  • System.out.println("productor quiere poner
    "d)
  • try
  • lockBuffer.lock()
  • while (numDatos tam) nolleno.await()
  • bi d
  • i (i 1) tam
  • numDatos
  • novacio.signal()
  • finallylockBuffer.unlock()

54
Productor/Consumidor
  • public int extraer() throws InterruptedException
  • System.out.println("consumidor quiere extraer"
    numDatos)
  • try
  • lockBuffer.lock()
  • while (numDatos 0) novacio.await()
  • int aux j
  • j (j 1) tam
  • numDatos--
  • nolleno.signal()
  • return baux
  • finally lockBuffer.unlock()

55
Barbero Dormilón
  • import java.util.concurrent.locks.
  • public class Barberia
  • private Lock BLock new ReentrantLock()
  • private Condition cBlibre BLock.newCondition()
  • private Condition cSillaOcupada
    BLock.newCondition()
  • private Condition cPuertaAbierta
    BLock.newCondition()
  • private Condition cSiguiente
    BLock.newCondition()
  • private boolean Blibre false
  • private boolean SillaOcupada false
  • private boolean PAbierta false

56
Barbero Dormilón
  • public void siguiente()
  • BLock.lock()
  • try
  • System.out.println("Barbero libre")
  • Blibre true
  • cBlibre.signal()
  • while (!SillaOcupada)
  • trycSillaOcupada.await()
  • catch (InterruptedException e)
  • finally
  • BLock.unlock()

57
Barbero Dormilón
  • public void finPelar()
  • BLock.lock()
  • try
  • PAbierta true
  • cPuertaAbierta.signal()
  • while (PAbierta)
  • trycSiguiente.await()
  • catch (InterruptedException e)
  • finally
  • BLock.unlock()

58
Barbero Dormilón
  • public void qPelar(int i)
  • BLock.lock()
  • try
  • while (!Blibre)
  • trycBlibre.await()
  • catch (InterruptedException e)
  • Blibre false
  • SillaOcupada true
  • System.out.println("Cliente "i" se sienta en
    la silla")
  • cSillaOcupada.signal()
  • while (!PAbierta)
  • trycPuertaAbierta.await()
  • catch (InterruptedException e)
  • System.out.println("Cliente "i" se va")
  • PAbierta false
  • cSiguiente.signal()
  • finally
  • BLock.unlock()

59
Barbero Dormilón
  • public void qPelar(int i)
  • BLock.lock()
  • try
  • while (!Blibre)
  • trycBlibre.await()
  • catch (InterruptedException e)
  • Blibre false
  • SillaOcupada true
  • System.out.println("Cliente "i" se sienta en
    la silla")
  • cSillaOcupada.signal()
  • while (!PAbierta)
  • trycPuertaAbierta.await()
  • catch (InterruptedException e)
  • System.out.println("Cliente "i" se va")
  • PAbierta false
  • cSiguiente.signal()
  • finally
  • BLock.unlock()

60
Barbero Dormilón
  • public class Barbero implements Runnable
  • Barberia b
  • public Barbero(Barberia b)
  • this.b b
  • public void run()
  • while (true)
  • b.siguiente()
  • System.out.println("Barbero Pela Cliente")
  • // Barbero pela cliente
  • b.finPelar()

61
Barbero Dormilón
  • public class cliente implements Runnable
  • Barberia b
  • int id
  • public cliente(Barberia b,int i)
  • this.b b
  • id i
  • public void run()
  • b.qPelar(id)

62
Barbero Dormilón
  • public class UsaBarberia
  • public static void main(String args)
  • final int N 125
  • Barberia b new Barberia()
  • Barbero bar new Barbero(b)
  • cliente c new clienteN
  • for (int i 0 iltN i)
  • ci new cliente(b,i)
  • Thread bh new Thread(bar)
  • bh.start()
  • Thread ch new ThreadN
  • for (int i 0 iltN i)
  • chi new Thread(ci)
  • for (int i 0 iltN i)
Write a Comment
User Comments (0)
About PowerShow.com