Está en la página 1de 8

Clase de algoritmos paralelos correspondiente a la semana del 27 al 31 de mayo del 2013 ALGORITMO DE DEKKER Y PETERSON I.

INTRODUCCION: CONCEPTOS PREVIOS 1. 1. LOS PROCESOS Un proceso es una entidad compuesta de un cdigo ejecutable secuencial, un conjunto de datos y una pila que se utiliza para la transferencia de parmetros, restauracin de llamadas recursivas o de interrupciones, etc. Una parte de la pila contiene el entorno del proceso (ver Figura5).

procesos, algunos de los cuales pueden incluir una nica accin. 1.2. ESTADOS Y OPERACIONES DE UN PROCESO Durante el tiempo de existencia de un proceso, ste se puede encontrar en uno de varios estados posibles. El cambio de un estado a otro depende de ciertas operaciones (ver Figura 6): Nuevo: El proceso ha sido creado por un usuario al lanzar un programa concurrente a ejecucin. En Ejecucin: Las instrucciones de mquina que conforman el cdigo fuente del proceso estn siendo ejecutadas por el procesador. Bloqueado: El proceso est esperando a que ocurra algn tipo de evento, por ejemplo, la realizacin de una operacin de entrada/salida. Listo: El proceso est en espera de que sus instrucciones sean ejecutadas por el procesador cuando el planificador del sistema operativo le d el turno para ello. Finalizado: El proceso ha terminado y todos los recursos que ha utilizado para ejecutarse son liberados.

Fig. 5. Modelo bsico de un Proceso Aun cuando el concepto de proceso es el mismo en todos los lenguajes de programacin concurrente, existen variaciones en cuanto al modelo de concurrencia que adoptan. Estas variantes se dan en aspectos como: La estructura: o Esttica: Cuando el nmero de procesos del programa concurrente es fijo y se conoce en tiempo de compilacin o Dinmica: Cuando los procesos pueden ser creados en cualquier momento. El nmero de procesos existentes en el programa concurrente slo se conoce en tiempo de ejecucin. El Nivel de Paralelismo: o Anidado: Cuando un proceso puede ser definido dentro de otro proceso. o Plano: Cuando los procesos slo pueden ser definidos en el nivel ms externo del programa. Relaciones entre Procesos: Se pueden crear jerarquas de procesos e interrelaciones entre ellos con el uso de los niveles de paralelismo anidados. o Relacin Padre/Hijo: Un proceso (el padre) es el responsable de la creacin de otro, el hijo. El padre ha de esperar mientras el hijo est siendo creado e inicializado o Relacin Guardian/Dependiente: El proceso guardin no puede terminar hasta que todos los procesos dependientes hayan terminado . Granularidad: Se puede hacer la divisin de paralelismo de grano fino y paralelismo de grano grueso. Un programa concurrente de grano grueso contiene relativamente pocos procesos, cada uno con una labor significativa que realizar. Los programas de grano fino contienen un gran nmero de
3

Transicin de estados de un estado a traves de operaciones 1.3. CONCURRENCIA La programacin concurrente tiene sus races en los sistemas operativos y en la programacin de sistemas, no en vano, los primeros programas concurrentes fueron los propios sistemas operativos de multiprogramacin en los que un solo procesador de gran capacidad deba compartir su tiempo entre muchos usuarios. En los aos 60s se introdujeron en las computadoras dispositivos controladores independientes de entradasalida llamados canales. Estos canales eran programables en s mismos. Los sistemas operativos fueron organizados como una coleccin de procesos ejecutndose concurrentemente (al mismo tiempo), algunos en los canales y otros ejecutndose en el procesador principal o CPU. Por otro lado en esos aos la programacin de sistemas con capacidades de concurrencia se haca a bajo nivel, en ensamblador, pues aparte de no disponer de lenguajes de alto nivel con capacidades de concurrencia, se primaba la supuesta eficiencia del cdigo escrito directamente en ensamblador. La aparicin en 1972 del lenguaje de alto nivel Concurrent Pascal, desarrollado por Brinch Hansen abri la puerta a otros lenguajes de alto nivel que incorporaban concurrencia. Desde entonces la programacin concurrente ha ido ganando inters y actualmente se utiliza muy a menudo en la

implementacin de numerosos sistemas. Tres grandes hitos fortalecen el hecho de que la programacin concurrente sea tan importante: La aparicin del concepto de Thread o hilo que hace que los programas puedan ejecutarse con mayor velocidad comparados con aquellos que utilizan el concepto de proceso La aparicin ms reciente de lenguajes como JAVA, lenguaje orientado a objetos de propsito general que da soporte directamente a la programacin concurrente mediante la inclusin de primitivas especficas. La aparicin del INTERNET que es un campo abonado para el desarrollo y la utilizacin de programas concurrentes. Cualquier programa de Internet en el que podamos pensar tales como un navegador, un chat, etc., estn programados usando tcnicas de programacin concurrente. 1.4. EXCLUSIN MUTUA Consiste en asegurar que dos procesos concurrentes no accedan a un mismo recurso comn al mismo tiempo, ya que ello puede llevar a incoherencia en la informacin que se procesa. Un problema tpico de la programacin concurrente donde la exclusin mutua se hace presente es el ya conocido: Problema de los jardines: Se desea controlar el nmero de visitantes a unos jardines. La entrada y la salida a los jardines se pueden realizar por dos puntos que disponen de 2 puertas. Se desea poder conocer en cualquier momento el nmero de visitantes a los jardines, por lo que se dispone de un dispositivo de clculo con conexin en cada uno de los dos puntos de entrada que le informan cada vez que se produce una entrada o una salida. Si analizamos el problema y lo llevamos al terreno de la programacin concurrente, podemos asociar el proceso P1 a un punto de entrada y el proceso P2 al otro punto de entrada. Ambos procesos se ejecutan concurrentemente y utilizan una nica variable, digamos x, para llevar la cuenta del nmero de visitantes. El incremento o decremento de la variable se produce cada vez que un visitante entra o sale por una de las puertas. De esta forma, la entrada de un visitante por una de las puertas hace que se ejecute la instruccin: x := x + 1 mientras que la salida de un visitante hace que se ejecute la instruccin: x := x 1 Aunque el proceso P1 y el proceso P2 se supongan ejecutados en procesadores distintos (lo cual no necesariamente es cierto), ambos utilizan la misma posicin de memoria para guardar el valor de la variable compartida, es decir, de x. Se puede dar la situacin de que el planificador de procesos del sistema permita el entrelazado (interfoliacin) de las operaciones elementales anteriores de cada uno de los procesos, lo cual inevitablemente producir errores que son difciles de detectar mediante una prueba del programa, ya que el que se produzcan depende de la temporizacin de dos procesos independientes. ste ejemplo muestra la clara necesidad de sincronizar (poner de acuerdo) de alguna manera la actuacin

de ambos procesos de forma que no se produzcan interferencias entre ellos. Para evitar este tipo de errores se pueden identificar aquellas regiones de los procesos que acceden a variables compartidas y dotarlas de la posibilidad de ejecucin como si fueran una nica instruccin. Surge entonces el concepto de regin crtica. Regin Crtica: Es la zona de cdigo de un proceso concurrente donde se utiliza un recurso compartido. La exclusin mutua se consigue impidiendo que dos o ms procesos concurrentes ejecuten a la vez su regin crtica. Una regin crtica solo puede ser ejecutada por un nico proceso concurrente siguiendo una nica secuencia de interfoliacin. Si algn otro proceso desea ejecutar su regin crtica, deber esperar a que aquel que actualmente ejecuta la suya termine y lo indique. Se necesita por tanto algn mecanismo (protocolos software) que indique a los procesos cuando uno de ellos entra o sale de la regin crtica . Esto se consigue con dos protocolos de software, uno de entrada y otro de salida (lock o semforo binario) que todo proceso debe forzosamente ejecutar antes y despus de ejecutar su regin crtica, y que constituyen un mecanismo de seguridad (bloqueo) que adems sobrecarga la ejecucin. Por ejemplo: Task body P is Begin Loop Resto_de cdigo; Pre_Protocolo; Regin Crtica; Post-Protocolo; End Loop; End P. Candado o semforo binario que produce la exclusin mutua El Pre_Protocolo y Post_Protocolo utilizan una variable comn11 a todos los procesos concurrentes la cual controla el acceso a la Regin Crtica. El Pre_Protocolo o Protocolo de Entrada consultar el valor de esa variable y en funcin de dicho valor dejar entrar o bloquear al proceso que desea entrar en su regin crtica. El Post_Protocolo o Protocolo de Salida modificar el valor de la variable comn para indicar que el recurso ya esta libre. La variable comn se utiliza como cauce de comunicacin entre los distintos procesos, con el objeto de acceder stos a sus regiones crticas con cierto orden. 1.5. LA SINCRONIZACIN Supongamos que tenemos dos procesos concurrentes ocupados uno de ellos en llenar un buffer circular de datos y el otro en vaciarlo. Puesto que el primer proceso no puede poner ms datos en el buffer si est lleno, y el segundo no puede tomar datos del buffer cuando est vaco, es necesario sincronizar la ejecucin de ambos procesos en funcin del estado del buffer, consiguiendo: 1. Que el proceso productor se bloquee cuando el buffer esta lleno 2. Que el proceso consumidor se bloquee cuando el buffer esta vaco 3. que el productor desbloquee al consumidor 4. que el consumidor desbloquee al productor
10

2.2. Primer Intento: ALTERNANCIA Existen diversos mecanismos software utilizados para conseguir la sincronizacin, uno de ellos es el candado (lock) o semforo binario, ya comentado en el apartado de la exclusin mutua, otro de ellos son las variables de condicin (monitores) que son variables comunes a los procesos concurrentes que comparten recursos, donde dependiendo del valor de la variable de condicin se produce una sincronizacin del tipo waitnotify, esperanotificacin, de manera que los procesos se comunican y sincronizan al acceder a sus recursos compartidos mediante mensajes que indican el bloqueo o desbloqueo de uno a otro u otros procesos va la variable de condicin. Imaginemos 2 esquimales y un agujero para pescar como recurso compartido. Existe un igl con un pizarrn. Solo uno de los esquimales puede acceder a la vez al pizarrn a la vez. Cuando uno de los esquimales quiere acceder al agujero para pescar debe consultar si tiene permiso para hacerlo en el pizarrn, si en el pizarrn se indica que el permiso lo tiene el otro esquimal espera un tiempo y lo vuelve a probar de nuevo ms tarde. Si en el pizarrn se indica que tiene permiso, ir a pescar. Una vez que termine con el agujero, ir al pizarrn y ceder el permiso al otro esquimal. De manera ms formal la codificacin del algoritmo es: PROGRAM PrimerIntento; VAR turno [1..2]; PROCEDURE P1; BEGIN REPEAT WHILE turno = 2 DO ; (* pasea *) ****** usa agujero de pesca ****** turno := 2; otras cosas FOREVER END; PROCEDURE P2; BEGIN REPEAT WHILE turno = 1 DO ; (* pasea *) ****** usa agujero de pesca ****** turno := 1; otras cosas FOREVER END; BEGIN turno := 1 COBEGUIN P1; P2 COEND END El inconveniente de este algoritmo es la alternancia obligada en el uso del recurso, si uno de los procesos es cancelado mientras usa el recurso nunca podr ceder su uso de nuevo.

II. ALGORITMO DE DEKKER Y PETERSON La solucin al problema de la exclusin mutua se atribuye al matemtico holands T. Dekker y fue presentada por Dijkstra en 1968. Se utiliza al igual que en otro algoritmo llamado Algoritmo de Peterson, una variable turno que sirve para establecer la prioridad relativa de los dos procesos, es decir, en caso de conflicto sta variable servir para saber, a quien se le concede el recurso y su actualizacin se realiza en la regin crtica, lo que evita que pueda haber interferencias entre los procesos. Explicaremos la utilidad de este algoritmo mediante un problema: 2.1 EL PROBLEMA DE LOS ESQUIMALES Intentaremos una manera de implementar el bloqueo a una regin crtica mediante el uso de una variable compartida en el problema denominado de los esquimales. Iremos refinando el algoritmo de manera que cada versin de dicho refinamiento presente el tipo de problemas que suele surgir en la implementacin de la concurrencia entre procesos. El problema de los esquimales mostrar el uso de las variables compartidas para implementar la exclusin mutua entre dos procesos. La ejecucin concurrente de los procesos la indicaremos mediante la estructura cobegin/coend. La palabra cobegin indica el comienzo de la ejecucin concurrente de los procesos que se sealan hasta la palabra coend. La accin de bloqueo se realiza con la activacin de la variable comn (indicador) y la de desbloqueo con su desactivacin.

2.3. Segundo Intento: FALTA DE EXCLUSION Siguiendo con el paradigma anterior, haremos uso de dos igles con su correspondiente pizarrn. Los pizarrones tienen dos indicadores, pescando o NOpescando, cada uno de los pizarrones corresponden a cada uno de los esquimales. Si queremos hacer uso del agujero para pescar deberemos consultar en el pizarrn del otro esquimal, si indica que est pescando saldremos y esperaremos para volverlo a intentar ms tarde. Si en el pizarrn pone NOpescando iremos a nuestro pizarrn y pondremos pescando. Cuando terminemos de usar el agujero de pescar iremos a nuestro pizarrn y pondremos NOpescando. De manera ms formal podramos codificar el algoritmo como: PROGRAM SegundoIntento; VAR pizarra1, pizarra2: NOpescando); PROCEDURE P1; BEGIN REPEAT WHILE pizarra2 = pescando pasea *) pizarra1 := pescando; *** usa agujero de pesca *** pizarra1 := NOpescando; otras cosas FOREVER END; PROCEDURE P2; BEGIN REPEAT WHILE pizarra1 = pescando pasea *) pizarra2 := pescando; *** usa agujero de pesca *** pizarra2 := NOpescando; otras cosas FOREVER END; BEGIN pizarra1 := NOpescando; pizarra2 := NOpescando; COBEGIN P1; P2 COEND END. Este algoritmo puede generar falta de exclusin mutua si los dos procesos tienen libre el recurso, a la vez consultan el estado de los oponentes y al comprobar que est libre los dos indican estado de uso del recurso y lo usan. (pescando

2.4. Tercer Intento: INTERBLOQUEO (Espera Infinita) Ahora actuaremos a la inversa para tratar de evitar la falta de exclusin mutua, cuando un proceso quiera utilizar el recurso, primero indica que quiere hacerlo y luego espera a que est libre. De manera ms formal podramos codificar el algoritmo como: PROGRAM TercerIntento; VAR pizarra1, pizarra2: NOpescando); (pescando

DO;

(*

PROCEDURE P1; BEGIN REPEAT pizarra1 := pescando; WHILE pizarra2 = pescando DO; pasea *) *** usa el agujero de pesca *** pizarra1 := NOpescando; otras cosas FOREVER END; PROCEDURE P2; BEGIN REPEAT pizarra2 := pescando; WHILE pizarra1 = pescando DO; pasea *) *** usa el agujero de pesca *** pizarra2 := NOpescando; otras cosas FOREVER END; BEGIN pizarra1 := NOpescando; pizarra2 := NOpescando; COBEGIN P1; P2 COEND END.

(*

(*

DO;

(*

En el caso que los dos esquimales estn sin pescar (NOpescando) y los dos pretendan acceder al agujero al mismo instante, los dos activarn en su pizarrn el estado de intencin de pescar (pescando), al ir a consultar la pizarra del oponente comprobarn que est pescando (o en intencin de hacerlo), en este caso ninguno de los dos esquimales podr acceder al recurso ni podr cambiar su estado. Hemos llegado a un estado de exclusin mutua (los dos procesos quieren acceder al mismo recurso, pero para que este les sea concedido los dos procesos deben realizar una accin que depende mutuamente de la accin del oponente para poderse realizar).

2.5. Cuarto Intento: ESPERA INFINITA Para solucionar el problema anterior aadiremos el trato de cortesa, si un proceso ve que su oponente quiere hacer uso del recurso, se lo cede. De manera ms formal podramos codificar el algoritmo como: VAR pizarra1, NOpescando); pizarra2: (pescando,

2.6 Quinto Intento: ALGORITMO DE DEKKER De manera formal la codificacin del algoritmo es: PROGRAMA AlgoritmoDeDekker; VAR pizarra1, pizarra1: NOpescando); Turno:[1..2]; (pescando,

PROCEDURE P1; BEGIN REPEAT pizarra1 := pescando; WHILE pizarra2 = pescando DO BEGIN (* tratamiento de cortesa *) pizarra1 := NOpescando; (* date una vuelta *) pizarra1 := pescando END; *** usa el agujero de pesca *** pizarra1 := NOpescando; otras cosas FOREVER END; PROCEDURE P2; BEGIN REPEAT pizarra2 := pescando; WHILE pizarra1 = pescando DO BEGIN (* tratamiento de cortesa *) pizarra2 := NOpescando; (* date una vuelta *) pizarra2 := pescando END; *** usa el agujero de pesca *** pizarra2 := NOpescando; otras cosas FOREVER END; BEGIN pizarra1 := NOpescando; pizarra2 := NOpescando; COBEGIN P1; P2 COEND END. Este tratamiento de cortesa puede conducir a que los procesos se queden de manera indefinida cedindose mutuamente el paso. Esta solucin no asegura que se acceda al recurso en un tiempo finito.

PROCEDURE P1; BEGIN REPEAT pizarra1 := pescando WHILE pizarra2 = pescando DO IF turno = 2 THEN BEGIN (* tratamiento de cortesa *) pizarra1 := NOpescando; WHILE turno = 2 DO; (* date vuelta *) pizarra1 := pescando END *** usa el agujero de pesca *** turno := 2; pizarra1 := NOpescando; otras cosas FOREVER END; PROCEDURE P2; BEGIN REPEAT pizarra2 := pescando WHILE pizarra1 = pescando DO IF turno = 1 THEN BEGIN (* tratamiento de cortesa *) pizarra2 := NOpescando; WHILE turno = 1 DO; (* date vuelta *) Pizarra2 := pescando END *** usa el agujero de pesca *** turno := 1; pizarra2 := NOpescando; otras cosas FOREVER END; BEGIN pizarra1 := NOpescando; pizarra2 := NOpescando; turno := 1; COBEGIN P1; P2 COEND END.

una

una

Este algoritmo asegura la exclusin mutua y est libre de interbloqueos.

Actividad Encargada: Plantear una solucin al modelo del auditor banquero (Ver Modelo en la prctica realizada en el laboratorio) utilizando el algoritmo de Dekker y Peterson.

ESQUIMALES QUINTO INTENTO(practica):


program QuintoIntento; var pizarra1, pizarra2: boolean; turno: integer; Process P1; var i:integer; begin repeat pizarra1:=true; while pizarra2=true do begin if turno=2 then begin (* tratamiento de cortesia *) pizarra1:=false; while turno=2 do; (* date una vuelta *) pizarra1:=true; end; end; (* Usa agujero de pesca *) writeln('Esquimal 1 Pescando...'); (* hace otras cosas *) turno:=2; pizarra1:=false; forever end; Process P2; var i:integer; begin repeat pizarra2:=true; while pizarra1=true do begin if turno=1 then begin (* tratamiento de cortesia *) pizarra2:=false; while turno=1 do; (* date una vuelta *) pizarra2:=true; end; end; (* Usa agujero de pesca *) writeln('ESQUIMAL 2 PESCANDO...'); (* hace otras cosas *) turno:=1; pizarra2:=false; forever end;

begin pizarra1:=true; pizarra2:=false; turno:=2; cobegin P1; P2; coend; end.

Una implementacin que simula la actividad del banco, en la cual las dos operaciones son realizadas por procesos diferentes, puede ser la siguiente (supongamos que el proceso se repite infinitamente): PROGRAM banco; CONST NCTAS=100; VAR Cuenta : array[1..NCTAS] of integer; (* Almacena los saldos *) i: Integer; PROCESS Auditor; VAR ci, Total:INTEGER; BEGIN REPEAT sleep(1); Total:=0; FOR ci:=1 TO NCTAS DO Total:= Total + Cuenta[ci]; Writeln(Total : , Total); FOREVER END; PROCESS banquero; VAR c1, c2, cant: Integer; BEGIN REPEAT c1 := RANDOM(NCTAS-1)+1; (* Origen *) c2 := RANDOM(NCTAS-1)+1; (* Destino *) cant:=0; IF (Cuenta[c1]>10) THEN cant := RANDOM(10); Cuenta[c1] := Cuenta[c1] - cant ; Cuenta[c2] := Cuenta[c2] + cant ; FOREVER END; BEGIN (* Principal *) For i:= 1 TO NCTAS DO cuenta[i]:=100; COBEGIN Banquero; Auditor COEND END.

PROGRAM problema5; CONST NCTAS=20; kRunTime = 120; kSleepTime = 10; VAR Cuenta:array[1..NCTAS] of integer; i: Integer; finished : boolean; flag1 : boolean; flag2 : boolean; turn : integer; PROCESS ContarSaldos; VAR ci, Total: INTEGER; BEGIN while not finished do begin flag1 := true; turn := 2; while (flag2 and (turn = 2)) do begin null; end; Total:=0; FOR ci:=1 TO NCTAS DO Total:=Total + Cuenta[ci]; Writeln('Total del Banco:',Total); flag1 := false; end; END;

Writeln('Nuevo Monto para Cuenta',c2,' es:',Cuenta[c2]); flag2 := false; end; END; PROCESS AUDITOR; begin while not finished do begin sleep(random(kSleepTime)); writeln('Un Momento...'); end; end; process supervisor; begin sleep(kRunTime); finished := true; end; (*MAIN*) BEGIN (*INICIAMOS LOS MONTOS DE 100 SOLES PARA CADA CUENTA*) For i:=1 TO NCTAS DO Cuenta[i]:=100; finished := false; flag1 := false; flag2 := false; turn := 1; (*EMPEZAMOS LOS PROCESOS*) COBEGIN supervisor; auditor; Operacion; ContarSaldos; COEND END.

PROCESS Operacion; VAR c1, c2, cant: Integer; BEGIN while not finished do begin flag2 := true; turn := 1; while (flag1 and (turn = 1)) do begin null; end; sleep(1); c1:=RANDOM(NCTAS-1)+1; c2:=RANDOM(NCTAS-1)+1; Writeln('Cuentas Aleatorias',c1,' y',c2); cant:=0; IF(Cuenta[c1]>10) THEN cant:=RANDOM(10); Cuenta[c1]:=Cuenta[c1] - cant; Writeln('Nuevo Monto para Cuenta',c1,' es:',Cuenta[c1]); Cuenta[c2]:=Cuenta[c2] - cant;

Solucin 2:
Otro aplicando otro algoritmo de exclusin mutua de Dekker: PROGRAM banco; CONST NCTAS=20; VAR Cuenta:array[1..NCTAS] of integer; i: Integer; finished : boolean; flag1 : boolean; flag2 : boolean;

PROCESS ContarSaldos; VAR ci, Total: INTEGER; BEGIN while not finished do begin

sleep(1); while flag1 do begin null; end; flag2 := true; Total:=0; FOR ci:=1 TO NCTAS DO Total:=Total + Cuenta[ci]; Writeln('Total del Banco:',Total); flag2 := false; end; END; PROCESS Operacion; VAR c1, c2, cant: Integer; BEGIN while not finished do begin while flag2 do begin null; end; (* flag1 := true; *) c1:=RANDOM(NCTAS-1)+1; c2:=RANDOM(NCTAS-1)+1; Writeln('Cuentas Aleatorias',c1,' y',c2); cant:=0; IF(Cuenta[c1]>10) THEN cant:=RANDOM(10); Cuenta[c1]:=Cuenta[c1] - cant; Writeln('Nuevo Monto para Cuenta',c1,' es:',Cuenta[c1]); Cuenta[c2]:=Cuenta[c2] + cant; Writeln('Nuevo Monto para Cuenta',c2,' es:',Cuenta[c2]); (* flag1 := false; *) end; END; BEGIN (*INICIAMOS LOS MONTOS DE 100 SOLES PARA CADA CUENTA*) For i:=1 TO NCTAS DO Cuenta[i]:=100; finished := false; flag1 := false; flag2 := false; (*EMPEZAMOS LOS PROCESOS*) COBEGIN Operacion; ContarSaldos; COEND END.

También podría gustarte