1
Hay varios niveles para expresar concurrencia: Nivel de Instrucción Nivel de Sentencia Nivel de Unidad Nivel de Programa 2
Hay varios niveles para expresar concurrencia: Nivel de Instrucción Nivel de Sentencia Nivel de Unidad Nivel de Programa Lenguajes de Programación 3
Hay varios niveles para expresar concurrencia: Nivel de Instrucción Nivel de Sentencia Nivel de Unidad Nivel de Programa Hoy nos centraremos 4
El concepto fundamental para concurrencia a este nivel es el de tarea: Una tareaes una unidadque puede estar ejecutando concurrentemente con otras unidades del mismo programa y que provee su propio hilo de ejecución. 5
Una tarease diferencia de un subprograma porque: Pueden iniciarse implícitamente Cuando son invocadas el invocador no necesita esperarque la tarea termine para continuar su ejecución Cuando una tarea termina puede que el control no retorne a la unidad invocadora 6
Las tareasse pueden comunicara través de: variables compartidas, mensajes o parámetros. Uno de los aspectos más importantes en el soporte para concurrencia de un lenguaje de programación es el mecanismo de sincronización 7
Hay dos tipos de sincronización: Cooperativa:cuando las tareas cooperan para algún objetivo, entonces una tarea debe esperarque otra finalice una actividad específica antes de poder continuar su ejecución. Competitiva:donde las tareas compiten por el usode un recurso de uso exclusivo. 8
Tres mecanismos utilizados por los lenguajes de programación para sincronizartareas: Semáforos Monitores Pasaje de mensajes sincrónico 9
Vamos a ver como implementar Productor Consumidor en Java y Ada 10
Vamos a ver como implementar Productor Consumidor en Java y Ada 11
Al depósito sólo puede acceder uno a la vez, por lo tanto compiten por el acceso ZZZZZ ZZZZZ ZZZZZ 12
Si el depósito está lleno los productores deben esperar, coordinando con los consumidores ZZZZZ ZZZZZ 13
Si el depósito esta vacío los consumidores deben esperar, coordinando con los productores ZZZZZ ZZZZZ 14
15
Java usa Hilospara expresar concurrencia. Los Hilosse utilizan a través de la clase Thread. Las unidades concurrentes serán métodos Run(), provisto por la clase Thread. Un Run() puede correr concurrentemente con otros Run(). Por lo tanto, una claseque quiera tener un método concurrente debe heredarde la clase Thread y dar implementación a Run(). 16
class Deposito{ itemcola C Cola de items con tamaño limitado Deposito(int tam){ C= new itemcola(tam); } 17
El depósito debe ser accedido de manera exclusiva, usando sincronización competitiva entre productor y consumidor Para esto JAVA permite usar métodos synchronized Mientras un método synchronizedejecutaningún otro método del objeto se ejecutará 18
class Deposito{ itemcola C Deposito(int tam){ C= new itemcola(tam); } synchronized void depositar(item i){ } synchronized item retirar(){ } 19
class Deposito{ itemcola C Deposito(int tam){ C = new itemcola(tam); } synchronized void depositar(item i){ C.encolar(i); } synchronized item retirar(){ itemi = C.desencolar(); return(i); } 20
Debemos usar sincronización cooperativa entre productor y consumidor, cuando el depósito esta lleno o vacío. wait(): bloqueaal hilo que lo invoque, poniéndolo en una lista de espera con todos los otros hilos que hayan llamado a waiten ese objeto. notifyall(): despiertaa todos los hilos que se encuentren en la lista de espera de ese objeto. Sólo pueden ser llamados desde métodos synchronized. 21
class Deposito{ itemcola C Deposito(int tam){ C = new itemcola(tam); } synchronized void depositar(item i){ while( C.llena() ) wait(); C.encolar(i); notifyall(); } synchronized item retirar(){ while( C.vacia() ) wait(); itemi = C.desencolar(); notifyall(); return( i ); } Usamos un Whileen ves vez de un IF por que el notifyalldespierta a todos!!! 22
class Productor extends Thread{ Deposito D; Productor(Deposito Dep){ D= Dep; } voidrun(){ while(true){ D.depositar(new Item()); } } 23
class Consumidor extends Thread{ Deposito D; Consumidor(Deposito Dep){ D= Dep; } voidrun(){ while(true){ itemi = D.retirar(); } } 24
Deposito d = newdeposito(20); Productor p1 = newproductor(d); Productor p2 = new Productor(d); Consumidor c1 = new Consumidor(d); Consumidor c2 = new Consumidor(d); p1.start(); p1.start(); c1.start(); c2.start(); 25
26
ADA expresa concurrencia utilizando Task. Administran datos compartidos e interactuan entre si mediante el pasaje de mensajes. Un Tasktiene una especificacióny un cuerpo. La interfazde una Taskesta dada por sus puntos de entrada entry, que son los lugares donde se aceptan mensajes de otras tareas. En el cuerpo del Taskse especifican los entry mediante clauslas accept. 27
Task Deposito is entry depositar(i: in item) entry retirar(i: out item) end Deposito 28
Task body Deposito is C: itemcola Begin accept depositar(i: in item) do (cuerpo depositar) accept retirar(i: out item) do (cuerpo retirar) End Cuando recibe un mensaje que puede aceptar, se ejecuta el cuerpo 29
Task body Deposito is C: itemcola Begin accept depositar(i: in item) do (cuerpo depositar) accept retirar(i: out item) do (cuerpo retirar) End Cuando no lo puede aceptar el Taskque envió el mensaje queda en cola de espera 30
Task body Deposito is C: itemcola Begin accept depositar(i: in item) do (cuerpo depositar) accept retirar(i: out item) do (cuerpo retirar) End Si un Taskllega a un accepty no hay mensajes, se suspende esperando mensajes en ese accept 31
Task body Deposito is C: itemcola Begin loop select accept depositar(i: in item) (cuerpo depositar) accept retirar(i: out item) (cuerpo retirar) El selectpermite que se elija de manera no determinista algún accept en su cuerpo 32
El when permite Task body Deposito is determinar cuándo se C: itemcola Begin acepta un mensaje en loop un punto entrada select (Sincronización coop) whennotllena( C)=> accept depositar(i: in item) do encolar(i, C) whennotvacia( C) => accept retirar(i: out item) do i = desencolar( C) 33
El acceso excluyente ya está garantizado, debido a la semántica de ejecución de las Task. En todo momento sólo puede haber un accept activo. Por este motivo, cuando lleguen mensajes y el depósito no esté disponible,los mensajes entrantes serán encolados en cada punto de entrada. Luego, cuando sea posible procesarlos, se elegirá algún mensaje entre todos los encolados. 34
Task Productor Task body Productor is Begin loop Deposito.depositar(itemNuevo) end loop end Porductor 35
TaskConsumidor Task body Consumidor is i:item begin loop Deposito.retirar(i) end loop end Consumidor. 36
En cuanto al mecanismo de sincronización cooperativa: En Java como vimos el programador debe Explicitar cuándo un hilo se bloqueay cuándo se despierta. En ADAel mecanismo de guardas combinado con las cláusulas acceptresuelve de manera automática esta interacción. Sólo se debe explicitar la condición de sincronización y el mecanismo provisto por el lenguaje resuelve el resto de manera transparente. Comparativamente, por lo tanto, el mecanismo provisto por JAVA es más propenso a errores del programador. 37
En Adala sincronizaciónes entre tareas por la mecánica de pasaje de mensajes. Por lo tanto la información compartida es manejada por las tareas. Es por eso que el depósito es un Taskmás. En JAVAesto es diferente, ya que los métodos synchronizedson entidades pasivas, siguiendo para esto un modelo de monitores. 38
Sebesta Concepts of Programaming Languages Cap. 13 39