14
1 Sistemas Operativos Tema 7. Concurrencia 1 © 1998-2012 José Miguel Santos – Alexis Quesada – Francisco Santana Contenidos Sistemas concurrentes El problema de la sección crítica Semáforos Monitores 2 Bibliografía Fundamentos de Sistemas Operativos S. Candela, C.R. García, A. Quesada, F.J. Santana, J.M. Santos. Thomson, 2007 Capítulo 3 Programación Concurrente J.T. Palma, M.C. Garrido, F. Sánchez, A. Quesada Capítulos 1, 2, 3, 4, 5 y 6 Principles of Concurrent and Distributed Programming M. Ben-Ari. Prentice Hall, 1990 Concurrent Programming A. Burns, G. Davies. Addison-Wesley, 1993 Capítulo 7 3 Contenidos Sistemas concurrentes El problema de la sección crítica Semáforos Monitores 4 Modelo del sistema Conjunto de procesos cooperativos Red de cajeros automáticos Sistema de reserva de billetes Servidor de impresión ... 5 ¿Qué es concurrencia? Definición de diccionario: coincidir en el espacio o en el tiempo dos o más personas o cosas. En Informática, se habla de concurrencia cuando hay una existencia simultánea de varios procesos en ejecución. Ojo, concurrencia existencia simultánea no implica ejecución simultánea. 6

So 07-concurrencia-6x1

Embed Size (px)

DESCRIPTION

AREGAERGFGHDFGTHGFHFDGVB NBVNDFGAFRGASFDGSDGGHDFHFDHSGHRTDHYRTHRTHBSDYDAVSIUDAUIWEAYWEIOUWEIUYEWIOUWEYEWIUOYEWIUEWYWEIUOYWEIUWEOYEWIOYEWIUWEYEWIOUYWEWIUOYEWOIUYWEIOUYWEIOWEUYWEOIYEIWOUYWEIOWEUYWEIOUYWEIOWEUYEWIOUYEWOIUWEYEOIUYeioruyqoiuewryewoiuryweoiruyweriouyweriouweryioweyriowueryoiweuryweiruoyweoiruyweriouyweriuewryowieuryewiuryewuiysdfuiyeiuxiuwifuoifuwifuwifuwifuwifuwifuwifu

Citation preview

Page 1: So 07-concurrencia-6x1

1

Sistemas Operativos Tema 7. Concurrencia

1

© 1998-2012 José Miguel Santos – Alexis Quesada – Francisco Santana

Contenidos

n  Sistemas concurrentes n  El problema de la sección crítica n  Semáforos n  Monitores

2

Bibliografía

n  Fundamentos de Sistemas Operativos q  S. Candela, C.R. García, A. Quesada, F.J. Santana, J.M. Santos.

Thomson, 2007 q  Capítulo 3

n  Programación Concurrente q  J.T. Palma, M.C. Garrido, F. Sánchez, A. Quesada q  Capítulos 1, 2, 3, 4, 5 y 6

n  Principles of Concurrent and Distributed Programming q  M. Ben-Ari. Prentice Hall, 1990

n  Concurrent Programming q  A. Burns, G. Davies. Addison-Wesley, 1993 q  Capítulo 7

3

Contenidos

n  Sistemas concurrentes n  El problema de la sección crítica n  Semáforos n  Monitores

4

Modelo del sistema

n  Conjunto de procesos cooperativos q  Red de cajeros automáticos q  Sistema de reserva de billetes q  Servidor de impresión q  ...

5

¿Qué es concurrencia?

n  Definición de diccionario: coincidir en el espacio o en el tiempo dos o más personas o cosas.

n  En Informática, se habla de concurrencia cuando hay una existencia simultánea de varios procesos en ejecución.

n  Ojo, concurrencia existencia simultánea no implica ejecución simultánea.

6

Page 2: So 07-concurrencia-6x1

2

Paralelismo y concurrencia

n  El paralelismo es un caso particular de la concurrencia.

n  Se habla de paralelismo cuando ocurre la ejecución simultánea de instrucciones.

7

Procesos cooperativos

n  Necesidades de sincronización y comunicación

n  Los procesos concurrentes tendrán necesidad de comunicarse información

n  Además, será necesario en ocasiones detener a un proceso hasta que se produzca un determinado evento o se den ciertas condiciones à sincronización

8

Técnicas de sincronización

n  Basadas en memoria compartida q  Inhibición de Interrupciones q  Espera activa q  Semáforos q  Regiones críticas q  Monitores

n  Basadas en el paso de mensajes q  Canales q  Buzones

9

Ejemplo 1: modificación concurrente de una variable

procedure  Ejemplo1  is        x:integer;    procedure  P1  is  begin    x:=x+10;  

end  P1;    procedure  P2  is  begin      if  x>100  then        Put_Line  (x);  

   else          Put_Line  (x-­‐50);      end  if;  end  P2;    

begin      x:=100;    COBEGIN        P1;        P2;    COEND;  

end  Ejemplo1;    

10

Ejemplo 2: bucles infinitos concurrentes procedure  Ejemplo2  is      contador:integer;  

procedure  Cuenta  is  begin  

 loop        …espera  a  que  pase  un  coche…        contador  :=  contador+1;    end  loop;  

end  Cuenta;    procedure  Imprime;  begin  

 loop        espera  una  hora        Put(“Coches  que  han  pasado:  “);    

         Put  (contador);        contador:=0    end  loop;  

end  Imprime;  

begin      contador:=0;    COBEGIN        Cuenta;        Imprime;    COEND;  

end  Ejemplo2;    

11

Ejemplo 3: búfer limitado

loop        producir_algo  (elem);        loop    

 exit  when  contador<N;        end  loop;        buffer(entra):=elem;        entra:=entra+1;        contador:=contador+1;  end  loop;    

N:  constant  integer:=...;  type  elemento  is  ...;  buffer:  array(0..N-­‐1)  of  elemento;  entra,sale:  mod  N:=0;  contador:  integer  range  0..N:=0;        

loop        loop    

 exit  when  contador>0;        end  loop;        elem:=buffer(sale);        sale:=sale+1;        contador:=contador-­‐1;        consumir  (elem);  end  loop;    

Productor Consumidor

12

Page 3: So 07-concurrencia-6x1

3

Problema al modificar datos compartidos

n  Ambas rutinas son correctas si se ejecutan por separado pero podrían NO funcionar si se ejecutan de manera concurrente

n  Supongamos que contador contiene en un momento dado el valor 5 y que las instrucciones “contador=contador+1” y “contador=contador-1” se ejecutan de forma concurrente (¡contador podría ser 4, 5 o 6!)

contador = contador + 1 contador=contador-1 registro1 := contador; registro2 := contador; registro1 := registro1 +1; registro2 := registro2 -1; contador : registro1; contador := registro2;

T0: productor registro1 := contador (registro1= 5) T1: productor registro1 := registro1+1 (registro1 = 6) T2: consumidor registro2 := contador (registro2 = 5) T3: consumidor registro2 := registro2 -1 (registro2 = 4) T4: productor contador := registro1 (contador = 6) T5: consumidor contador := registro2 (contador = 4)

13

Contenidos

n  Sistemas concurrentes n  El problema de la sección crítica n  Semáforos n  Monitores

14

Sección crítica: modelo del sistema n  N procesos intentan acceder a un recurso

compartido en un bucle infinito: loop      Sección_No_Crítica  (SNC);      Pre_Protocolo;      Sección_Crítica  (SC);      Post_Protocolo;  end  loop;  

n  Sección crítica: segmento de código donde se accede a datos compartidos con otros procesos

15

Sección crítica: modelo del sistema (2) n  Nunca puede haber más de un proceso en la

sección crítica (exclusión mutua) n  Los pre y post protocolos serán algoritmos para

garantizar que se cumple la exclusión mutua

16

Requisitos de la solución

n  Exclusión mutua n  Progreso: si ningún proceso está en sección

crítica y hay procesos que desean entrar en su s.c., sólo estos últimos participarán en la decisión y ésta se tomará en un tiempo finito.

n  Espera limitada: hay un límite para el número de veces que otros procesos pueden adelantarse a un proceso que quiere entrar en s.c.

17

Importante

n  Suponemos que cada proceso se ejecuta a una velocidad distinta de cero

n  No podemos hacer suposiciones acerca de las velocidades relativas de los procesos

18

Page 4: So 07-concurrencia-6x1

4

Solución trivial: cortar la multiprogramación n  Si suspendemos la multiprogramación,

desaparece el problema de acceso a los datos compartidos…

n  …pero perdemos todas las ventajas de la multiprogramación

n  Hay que buscar una solución menos radical

19

Solución del hardware: inhibir las interrupciones n  Antes de que un proceso entre en su sección

crítica, se inhiben las interrupciones n  Así es imposible que el proceso sea

expulsado de la CPU mientras está accediendo al dato compartido

n  Al salir de la SC, se rehabilitan las interrupciones

20

Inhibir las interrupciones: problemas n  Mientras un proceso está en SC, se

suspende toda la concurrencia en el sistema à no se le da oportunidad a otros procesos que no están accediendo al recurso compartido

n  Esta técnica no se puede implementar en un multiprocesador

21

Soluciones con espera activa

n  La sincronización se basa en que un proceso espera mediante la comprobación continua de una variable, manteniendo ocupada la CPU.

n  Soluciones Software

n  Soluciones Hardware

22

Intento ingenuo: usar un indicador de disponibilidad

23

-­‐-­‐  variable  global  -­‐-­‐  indica  si  la  sección  crítica  está  libre  libre:  boolean  :=  true;  

-­‐-­‐  código  que  ejecuta  cada  proceso  loop      …  sección  no  crítica  …      loop            exit  when  libre;        end  loop;      libre  :=  false;      …  sección  crítica  …      libre  :=  true;  end  loop;  

loop      SNC2;      loop            exit  when  turno=2;  

end  loop;      SC2;      turno:=1;  end  loop;  

 

loop      SNC1;      loop            exit  when  turno=1;      end  loop;      SC1;      turno:=2;  end  loop;  

Primer intento serio: variable turno

turno:  positive  range  1..2  :=  1;  

24

(solución para dos procesos)

proceso 1 proceso 2

Page 5: So 07-concurrencia-6x1

5

Discusión del primer intento

n  ¿Exclusión mutua? n  ¿Espera limitada? n  ¿Progreso?

25

loop      SNC1;      loop          exit  when  libre2;      end  loop;      libre1:=false;      SC1;      libre1:=true;  end  loop;  

loop      SNC2;      loop          exit  when  libre1;      end  loop;      libre2:=false;      SC2;      libre2:=true;  end  loop;  

Segundo intento: avisadores

libre1,  libre2:  boolean  :=  true;  

26

proceso 1 proceso 2

Tercer intento

loop      SNC1;      libre1:=false;      loop          exit  when  libre2;      end  loop;          SC1;      libre1:=true;  end  loop;  

loop      SNC2;      libre2:=false;        loop          exit  when  libre1;      end  loop;          SC2;      libre2:=true;  end  loop;  

libre1,libre2:  boolean  :=  true;  

27

proceso 1 proceso 2

loop      SNC1;      libre1:=false;      turno:=  2;      loop            exit  when  libre2  or            turno=1;  

   end  loop;      SC1;      libre1:=true;  end  loop;  

loop      SNC2;      libre2:=false;      turno:=  1;      loop          exit  when  libre1  or            turno=2;  

   end  loop;      SC2;      libre2:=true;  end  loop;  

Algoritmo de Peterson - ¡¡FUNCIONA!!

   libre1,  libre2:  boolean  :=  true;      turno:  positive  range  1..2  :=  1;  

28

Solución para N procesos: Algoritmo de la panadería (Lamport)

cogiendonumero:  array(1..N)  of  boolean  :=  (others=>false);  num:  array(1..N)  of  natural  :=  (others=>0);  

29

loop  –-­‐  código  del  proceso  “i”      Sección  no  crítica  (i);      cogiendonumero(i):=true;          num(i)  :=    1  +  MAX(num(1)  ...  num(n));      cogiendonumero(i):=false;      for  j  in  1..N  loop          loop                exit  when  not  cogiendonumero(j);          end  loop;          loop              exit  when  i=j  or  num(j)=0  or                                  num(j)>num(i)  or  (num(j)=num(i)  and  j>i);          end  loop;      end  loop;      Sección  crítica  (i);      numero(i):=0;  end  loop;  

Soluciones hardware

n  Inhibir interrupciones (muy drástico)

n  Instrucciones atómicas test-and-set o SWAP.

30

Page 6: So 07-concurrencia-6x1

6

Instrucciones atómicas

n  Inventadas en los años 60. n  Permiten evaluar y asignar un valor a una

variable de forma atómica. n  test-and-set(B): Pone B a true y devuelve el antiguo

valor de B. (Evaluar-y-Asignar(B)) n  SWAP(A,B): Intercambia los valores de A y B.

(Intercambiar(A,B))

n  Si disponemos de estas instrucciones, se simplifica muchísimo el problema de la sección crítica.

31

Ejemplos de algoritmos

loop      Sección  no  crítica;      loop          exit  when                  Test_and_Set(llave)=false;      end  loop;      Sección  crítica;      llave:=false;  end  loop;  

loop      Sección  no  crítica;      aux:=true;  -­‐-­‐  ¡variable  local!      loop          Swap(llave,aux);          exit  when  aux=false;      end  loop;      Sección  crítica;      llave:=false;  end  loop;  

32

usando test-and-set

usando swap

Solución completa (test-and-set)

j:  mod  N;  llave:boolean;    loop      SNCi;      esperando(i):=true;        llave:=true;        while  esperando(i)  and  llave  loop            llave:=Test_and_Set(cerradura);        end  loop;      esperando(i):=false;        SCi;        j:=i+1;      while  (j/=i)  and  not  esperando(j)  loop          j:=j+1;      end  loop;      if  j=i  then          cerradura:=false;      else          esperando(j):=false;          end  if;  end  loop;  

 esperando:  array(0..N-­‐1)  of  boolean  :=  (others  =>  false);    cerradura:  boolean  :=  false;  

33

Contenidos

n  Introducción n  El problema de la sección crítica n  Semáforos n  Monitores

34

Semáforos

n  Edsger Dijkstra, 1965 n  Objetivo: herramienta universal para

sincronizar procesos, que sirva como componente básico para construir algoritmos concurrentes

35

Concepto de semáforo

n  Dijkstra lo definió como una variable entera S con dos operaciones atómicas:

n  P(S): esperar a que S>0; S:=S-1;

n  V(S): S:=S+1;

n  NOTA: el semáforo no puede adquirir valores negativos

36

Page 7: So 07-concurrencia-6x1

7

Semáforos: otras notaciones

n  P(s) = wait(s) = espera (s) n  V(s) = signal(s) = señal (s)

n  (se utilizan varias notaciones para las operaciones de los semáforos, pero todas significan lo mismo)

37

Ejemplo: sección crítica resuelta con semáforos

n  Usamos un único semáforo inicializado a uno.

begin      Sección  no  crítica      wait(s)      Sección  crítica      signal(s)  end;  

38

Semáforos: esperar por eventos y condiciones n  Se asocia un semáforo, inicializado a cero, al evento

por el que queremos esperar. Cuando un proceso ha hecho que se cumpla una determinada condición, lo indica ejecutando un signal(c). Un proceso esperará a que la condición sea cierta mediante un wait(c).

P1  begin    S1;    signal(c);    S2;  

end;    

P2  begin    R1;    wait(c);    R2;  

end;    

39

Semáforos: ejercicios

n  Ejercicios q  a.-) Resolver el problema de la sección crítica con n

procesos q  b.-) Resolver diversos problemas de sincronización

n  b.1.-) Sean P1 y P2 dos procesos concurrentes. Modificar el código de ambos procesos de forma que el conjunto de sentencias R2 del proceso 2 se ejecute después de que se haya ejecutado el conjunto de sentencias S1 del proceso 1.

P1  begin      S1;      S2;  end;    

P2  begin      R1;      R2;  end;    

40

Semáforos: ejercicios

q  b.2.-) Realizar un pequeño programa que se ajuste al siguiente diagrama (o grafo) de precedencia (suponiendo que disponemos de las herramientas siguientes: sentencia concurrente cobegin/coend )

A

B

C

D

41

Semáforos: ejercicios

q  b.3.-) Realizar un pequeño programa que se ajuste al siguiente diagrama (o grafo) de precedencia (suponiendo que disponemos de las herramientas siguientes: sentencia concurrente cobegin/coend y semáforos)

A

B

C

D

42

Page 8: So 07-concurrencia-6x1

8

Semáforos: implementación con espera activa

wait(s):        while  s<=0  do  nada;        s:=s-­‐1;    signal(s):        s:=s+1;  

43

n  También llamados spinlocks

Semáforos: implementación sin espera activa

n  Suponemos que el SO proporciona unas operaciones para bloquear y desbloquear procesos

type  Semáforo  is  record    valor:integer;    L:  Lista<Proceso>;  

end  record;  

signal(s):    s.valor  :=  s.valor+1;  

     if  s.valor<=0  then              L.extraer(proceso);              despertar(proceso);        end  if;          

wait(s):        s.valor  :=  s.valor-­‐1;        if  s.valor<0  then              L.insertar(procesoActual);              bloquear(procesoActual);        end  if;  

44

Semáforos: la implementación debe garantizar atomicidad n  Es crítico que las operaciones se ejecuten

de forma atómica n  Entorno uniprocesador:

q  Inhibir interrupciones n  Entorno multiprocesador:

q  Instrucciones hardware especiales q  Aplicar un algoritmo de sección crítica con

espera activa

45

Semáforos binarios

n  Los semáforos vistos reciben el nombre de semáforo general o semáforo de conteo

n  Un semáforo que sólo puede tomar los valores 0 y 1 recibe el nombre de semáforo binario

46

Ejercicio

n  Implementación de un semáforo de conteo con semáforos binarios

47

Problemas clásicos de sincronización n  Problema del búfer limitado n  Problema de los lectores y escritores

q  1er problema: prioridad para los lectores q  2º problema: prioridad para los escritores

n  Problema de los filósofos comensales

48

Page 9: So 07-concurrencia-6x1

9

Búfer limitado

loop        ...        producir  un  elemento  elem        ...        wait(hayHuecos);        wait(cerradura);        buffer(entra):=elem;        entra:=entra+1;        signal(cerradura);        signal(hayElementos);  end  loop;    

N:  constant  integer:=...;  type  elemento  is  ...;  buffer:  array(0..N-­‐1)  of  elemento;  entra,sale:  mod  N:=0;  hayElementos:  Semaphore  :=0;  hayHuecos:  Semaphore  :=N;  cerradura:  Semaphore  :=1;      

loop        wait(hayElementos);        wait(cerradura);        elem:=buffer(sale);        sale:=sale+1;        signal(cerradura);        signal(hayHuecos);        ...        consumir  elemento  elem        ...  end  loop;    

Productor Consumidor

49

Lectores y escritores

n  Esquema útil para gestionar el acceso a una base de datos: q  Puede haber varios lectores accediendo a la BD

de forma concurrente q  Sólo puede haber un escritor trabajando q  No puede haber lectores y escritores al mismo

tiempo q  … y si se puede, que no haya inanición

50

Lectores y escritores: dos variantes n  Primera variante: prioridad para los lectores

q  Si un escritor está esperando, se le pueden adelantar otros lectores

q  Ojo, riesgo de inanición para los escritores n  Segunda variante: prioridad para los

escritores q  Si hay escritores esperando por la BD, los

lectores que van llegando nuevos se deben esperar hasta que todos los escritores finalicen

q  Ahora hay riesgo de inanición para los lectores

51

Lectores y escritores: 1ª variante

loop        wait(cerradura);        nlectores:=nlectores+1;        if  nlectores=1  then              wait(escritura);        signal(cerradura);        LEER  DE  LA  BD;        wait(cerradura);        nlectores:=nlectores-­‐1;        if  nlectores=0  then              signal(escritura);        signal(cerradura);  end  loop;    

cerradura:  Semaphore  :=1;  escritura:  Semaphore  :=1;  nlectores:  natural  :=0;  

loop        wait(escritura);        ESCRIBIR  EN  LA  BD;        signal(escritura);  end  loop;    

Lector Escritor

52

Lectores y escritores: 2ª variante

53

wait(cerrojo);      while  escribiendo  or                  nesc>0  loop          signal(cerrojo);          wait(cerrojo);      end  loop;      nlec  :=  nlec  +  1;    signal(cerrojo);  …  leer  de  la  BD  …  wait(cerrojo);      nlec  :=  nlec  –  1;  signal(cerrojo);  

cerrojo  :  Semaphore  :=  1;  escribiendo  :  boolean  :=  false;  nlec,nesc  :  natural  :=  0;  

wait(cerrojo);      nesc  :=  nesc  +  1;      while  escribiendo  or                  nlec>0  loop          signal(cerrojo);          wait(cerrojo);      end  loop;      nesc  :=  nesc  -­‐  1;      escribiendo  :=  true;    signal(cerrojo);  …  escribir  en  la  BD  …  wait(cerrojo);      escribiendo  :=  false;  signal(cerrojo);  

Lector Escritor

Los filósofos

54

Page 10: So 07-concurrencia-6x1

10

Los filósofos: modelo simple

loop        wait(palillo(i));        wait(palillo(i+1  mod  5));        ...        COMER;        ...        signal(palillo(i));        signal(palillo(i+1  mod  5);        ...        PENSAR;        ...  end  loop;    

palillo:  array(0..4)  of  Semaphore  :=  (others=>1);  

55

Filósofos: ojo al interbloqueo

n  La solución anterior puede entrar en un estado de bloqueo mutuo entre todos los filósofos à interbloqueo

n  Posibles soluciones: q  Algoritmo asimétrico filósofos pares/impares q  Impedir a más de cuatro filósofos entrar a pedir

los palillos q  Coger los dos palillos de forma atómica (o coges

los dos, o no coges ninguno)

56

Los semáforos ayudan, pero tienen limitaciones…

n  Los semáforos son una herramienta de bajo nivel, que requiere un uso disciplinado y cuidadoso.

n  Es muy fácil cometer errores de uso con semáforos.

n  Veamos algunos ejemplos…

57

¿dónde está el fallo?

Sem = 0 P (sem) … sección crítica … V (sem)

58

¿dónde está el fallo?

Sem  =  1    void  rutina_en_exclusion_mutua  ()  {        P  (Sem)          …  código  de  sección  crítica          if  (  error  )  return;          …  más  código  de  sección  crítica        V  (sem)  }  

59

Más problemas…

Proceso 1 P (impresora) P ( disco ) … usar disco e impresora

V (disco) V (impresora)

Proceso 2 P (disco) P ( impresora ) … usar disco e impresora

V (impresora) V (disco)

60

Dos procesos que acceden a recursos compartidos: ¿qué ocurre al ejecutarlos al mismo tiempo?

Page 11: So 07-concurrencia-6x1

11

Herramientas de alto nivel

n  Objetivo: introducir en el lenguaje de programación herramientas de sincronización que sean más seguras que los semáforos

n  Ejemplos: q  Regiones críticas q  Monitores y variables condición

61

Regiones críticas condicionales

n  Abstracción de un bloque de código que accede a recursos compartidos.

n  Garantiza exclusión mutua. n  El código sólo se ejecuta si la condición

asociada a la región crítica es cierta. n  Ejemplo:

 region  Búfer  when  Nelementos  >  0  {        //  este  código  se  ejecuta  en  exclusión  mutua        //  y  sólo  se  ejecuta  si  Nelementos  >  0        …  consumir  un  elemento  del  búfer  …        Nelementos  =  Nelementos  –  1;  }  

62

Regiones críticas condicionales

n  Se plantearon en 1972 (Brinch Hansen, Pascal Concurrente)

n  Gran fuerza expresiva, el código queda mucho más legible y compacto

n  Problema: implementación muy costosa, comparada con el código escrito a mano con semáforos

n  Por ese motivo, nunca llegaron a prosperar como herramienta de uso común

63

Contenidos

n  Introducción n  El problema de la sección crítica n  Semáforos n  Monitores

64

Monitor

n  Propuesto por Hoare (1972) n  Tipo abstracto de datos

q  Estructura de datos privada q  Operaciones públicas

+ q  Exclusión mutua q  Sincronización (variables condición)

65

Monitor: ejemplo básico

66

monitor  Contador  {      //  operaciones  públicas      public  Contador  ()  {  valor  =  0;  }      public  void  incrementa()  {  valor++;  }      public  int  actual()  {  return  valor;  }        int  valor;    //  variable  interna  privada  };    Contador.incrementa();  V  =  Contador.actual();    Si varios procesos intentan manipular el monitor al mismo tiempo, van entrando de uno en uno: no puede haber más de un proceso trabajando con el monitor en cada momento.

Page 12: So 07-concurrencia-6x1

12

Monitor: estructura interna

67

Variables condición

n  Una variable condición sirve para gestionar una cola de espera por el monitor

n  Dos operaciones q  x.wait à bloquea al proceso y lo mete en la cola “x”

q  x.signal à desbloquea a un proceso de la cola “x”; si no hay procesos en “x”, no hace nada

68

Variables condición: ejemplo

69

monitor  Contador  {      Condition  cola;      public  Contador  ()  {  valor  =  0;  }        public  void  BloqueaHastaQueValgaDiez()  {          if  (  valor  <  10  )  {  cola.wait();  }      }        public  void  Incrementa()  {            valor++;          if  (  valor  ==  10  )  {  cola.signal();  }      }        int  valor;  };    

Monitor con variables condición

código de inicialización

x y

datos compartidos

colas asociadas a las variables condición x e y

cola de ingreso

...

operaciones

70

Qué ocurre tras un “signal”

n  ¿ Qué ocurre cuando un proceso P realiza una operación signal sobre una variable condición x y existe un proceso suspendido Q asociado a dicha variable?

n  Estilo Hoare à se reanuda Q inmediatamente n  Estilo Mesa à Q se desbloquea, pero espera a que

P abandone el monitor

n  El estilo Mesa es el más utilizado en los lenguajes de programación actuales

71

Qué ocurre tras un “signal” (2)

n  Si varios procesos están suspendidos por la condición x y algún proceso ejecuta x.signal, ¿ qué proceso se reanuda? q  FIFO à desbloqueamos al más antiguo q  Por prioridades à conveniente en sistemas de

tiempo real

72

Page 13: So 07-concurrencia-6x1

13

Ejemplo: un semáforo implementado con un monitor

73

monitor  Semáforo  {      int  valor;      Condition  cola;        public  Semáforo  (int  val)  {  valor  =  val;  }        public  void  P()  {          while  (  valor  ==  0  )  {  cola.wait();  }          valor-­‐-­‐;      }        public  void  V()  {            valor++;          cola.signal();      }  };  

Ejemplo: búfer limitado

74

monitor  Búfer  {      Condition  hayHuecos,  hayItems;      int  nitems  =  0;      const  int  N  =  …;      public  void  insertar  (Item  x)  {          while  (  nitems==N  )  {  hayHuecos.wait();  }          …  introducir  x  en  el  búfer  …          nitems++;          hayItems.signal();      }  

   public  Item  extraer()  {          while  (  nitems==0  )  {  hayItems.wait();  }          Item  x  =  …  extrae  algo  …          nitems-­‐-­‐;          hayHuecos.signal();          return  x;      }  };  

Cómo se implementa un monitor

75

monitor  MiMonitor  {    public  void  oper1  (…)  {  …  }    public  void  oper2  (…)  {  …  }  };  

class  MiMonitor  {      Semáforo  cerrojo  =  1;      public  void  oper1  (…)  {          cerrojo.P();          …  cuerpo  de  oper1  …          cerrojo.V();      }      public  void  oper2  (…)  {          cerrojo.P();          …  cuerpo  de  oper2  …          cerrojo.V();      }  };  

El compilador genera un código parecido a este:

El cerrojo garantiza que no puede haber más de un proceso dentro del monitor

Cómo se implementa un monitor: variables condición

76

monitor  MiMonitor  {    Condition  c;    …    c.wait();    …    c.signal();    …  };  

monitor  MiMonitor  {      Semáforo  cerrojo  =  1;      Semáforo  c_queue  =  0;      int  c_count  =  0;  

c_count++;  cerrojo.V();  //  1.  libero  el  monitor  c_queue.P();  //  2.  me  bloqueo  en  la  cola  cerrojo.P();  //  3.  cuando  me  desbloqueen                            //        debo  recuperar  el  monitor  

   if  (c_count>0)  {  //  si  hay  alguien  esperando          c_count-­‐-­‐;          //  lo  desmarco          c_queue.V();      //  y  lo  desbloqueo      }  

Monitores: ejemplos más avanzados

77

Lectores y escritores (1)

78

monitor  BaseDatos  {      public  EmpiezaLectura()  {  …  }      public  TerminaLectura()  {  …  }      public  EmpiezaEscritura()  {  …  }      public  TerminaEscritura()  {  …  }  };    void  Leer()  {  //  Lo  que  debe  ejecutar  un  lector      BaseDatos.EmpiezaLectura();      …  leer  de  la  BD  …      BaseDatos.TerminaLectura();  }    void  Escribir()  {  //  Lo  que  debe  ejecutar  un  escritor      BaseDatos.EmpiezaEscritura();      …  escribir  en  la  BD  …      BaseDatos.TerminaEscritura();  }  

Page 14: So 07-concurrencia-6x1

14

Lectores y escritores (2)

79

monitor  BaseDatos  {      Condition  leer,  escribir;      int  nlec=0,  lecesperan=0;      bool  escribiendo  =  false;        public  EmpiezaLectura()  {          while  (escribiendo)  {              lecesperan++;                leer.wait();              lecesperan-­‐-­‐;  }          nlec++;          leer.signal();  //  desbloquea  en  cadena  al  resto      }          public  TerminaLectura()  {          nlec-­‐-­‐;          if  (nlec==0)  {  escribir.signal();  }      }  

Lectores y escritores (y 3)

80

   public  EmpiezaEscritura()  {          while  (nlec>0  ||  escribiendo)  {  escribir.wait();  }          escribiendo  =  true;      }          public  TerminaEscritura()  {          escribiendo  =  false;          if  (lecesperan  >  0)  {  leer.signal();  }          else  {  escribir.signal();  }      }   };

Filósofos (1): especificación del monitor

81

monitor  MesaFilósofos  {  

   //  estado  interno  del  sistema      const  int  N=5;      Condition  puedeComer[N];      enum  Estado  {  pensando,  hambriento,  comiendo  };      Estado  estado[N]  =  {  others  =>  pensando  };  

   //  operaciones  públicas  (ver  siguientes  páginas)      public  CogePalillos  (  int  filosofo  )  {  …  }      public  SueltaPalillos  (  int  filosofo  )  {  …  }        //  operación  auxiliar  interna      private  compruebaQuePuedeComer  (  int  filosofo  )  {  …  }  

 };  

Filósofos (2): ejemplo de uso

82

void  VidaDelFilósofo  (  int  unFilosofo  )  {        loop  {          piensaUnPoco();          MesaFilósofos.CogePalillos  (unFilosofo);          comeArroz();          MesaFilósofos.SueltaPalillos  (unFilosofo);      }  }  

Filósofos (3): rutina auxiliar

83

//  operación  privada  dentro  del  monitor  MesaFilósofos  

private  compruebaQuePuedeComer  (  int  filosofo  )  {          int  vecinoDerecha  =  (filosofo+1)  %  N;          int  vecinoIzquierda  =  (filosofo-­‐1+N)  %  N;                if  (  estado[vecinoIzquierda]  !=  comiendo  &&                    estado[vecinoDerecha]  !=  comiendo  )  {                estado[filosofo]  =  comiendo;                puedeComer[filosofo].signal();          }      }  

Filósofos (y 4): operaciones públicas del monitor

84

   public  CogerPalillos  (  int  filosofo  )  {          estado[filosofo]  =  hambriento;          compruebaQuePuedeComer(filosofo);          if  (  estado[filosofo]  !=  comiendo  )  {                puedeComer[filosofo].wait();          }      }        public  SoltarPalillos  (  int  filosofo  )  {          estado[filosofo]  =  pensando;          int  vecinoDerecha  =  (filosofo+1)  %  N;          int  vecinoIzquierda  =  (filosofo-­‐1+N)  %  N;          compruebaQuePuedeComer  (vecinoDerecha);          compruebaQuePuedeComer  (vecinoIzquierda);      }