Concurrencia: Exclusión Mútua y Sincronización

58
1 Concurrencia: Exclusión Mútua y Sincronización Capítulo 5

description

Concurrencia: Exclusión Mútua y Sincronización. Capítulo 5. Concurrencia. Concurrencia abarca conceptos tales como Comunicación entre procesos Compartición y competición de recursos compartidos Sincronización de actividades de multiples procesos colaborativos - PowerPoint PPT Presentation

Transcript of Concurrencia: Exclusión Mútua y Sincronización

Page 1: Concurrencia:  Exclusión Mútua y Sincronización

1

Concurrencia: Exclusión Mútua y Sincronización

Capítulo 5

Page 2: Concurrencia:  Exclusión Mútua y Sincronización

2

Concurrencia

• Concurrencia abarca conceptos tales como– Comunicación entre procesos

– Compartición y competición de recursos compartidos

– Sincronización de actividades de multiples procesos colaborativos

– Asignación de la CPU a los procesos

• Concurrencia no sólo surge en sistemas multiprocesadores o sistemas distribuidos, sino también en sistemas monoprocesadores con multiprogramación

Page 3: Concurrencia:  Exclusión Mútua y Sincronización

3

Concurrencia

Page 4: Concurrencia:  Exclusión Mútua y Sincronización

4

Principios de concurrencia

• No se puede asumir la velocidad relativa y el orden de ejecución de los procesos, la cual depende de– Las actividades de otros procesos o hebras

– El manejo de interrupciones

– La política de scheduling del SO

• Surgen problemas como – Compartición de recursos globales

– Administración eficiente de recursos. ¿Qué pasaría si el SO asigna un recurso de I/O a un proceso y éste inmediatamente se suspende?

– Difícil encontrar errores de programación. Los errores de sincronización y concurrencia son típicamente poco determinísticos.

Page 5: Concurrencia:  Exclusión Mútua y Sincronización

5

Un ejemplo simple

void echo(){

chin = getchar(); // asuma que chin is compartidachout = chin;putchar(chout);

}

Proceso P1 Proceso P2. .chin = getchar(); .. interrupción chin = getchar();chout = chin; chout = chin;putchar(chout); . interrupción. putchar(chout);. .

• Solución: Permitir que sólo un proceso ejecute la función a la vez

Page 6: Concurrencia:  Exclusión Mútua y Sincronización

6

Condición de carrera (race condition)

• Una condición de carrera ocurre cuando varios procesos o hebras leen y escriben datos compartidos y el resultado final depende del orden en que se ejecuten las instrucciones

• Ejemplo: Inicialmente, b=1, c=2, variables compartidas

P1 P2

b = b + c c = b + c

Page 7: Concurrencia:  Exclusión Mútua y Sincronización

7

Interacción entre Procesos

• Procesos no tienen conocimiento de la existencia de otros procesos – Aunque los procesos no trabajen colaborativamente, el SO debe administrar la competencia por recursos del sistema

• Procesos conocen indirectamente la existencia de otros – Saben que los recursos que accesan son compartidos con otros procesos

• Procesos que directamente conocen la existencia de otros procesos– Conocen el pid de los otros procesos

– Se comunican explícitamente

– Cooperan en alguna tarea

Page 8: Concurrencia:  Exclusión Mútua y Sincronización

8

Page 9: Concurrencia:  Exclusión Mútua y Sincronización

9

Cocurrencia en competencia de recursos

• Dos o más procesos necesitan accesar un (o más) recurso durante sus ejecuciones.

• Los procesos no saben de la existencia de otros procesos y sus operaciones no deben ser afectadas por la ejecución de otros procesos.

• Entonces, los procesos no deben afectar el estado de los recursos.

• Problemas potenciales de control– Exclusion mútua - sectiones críticas

• Sólo un programa a la vez puede ejecutar su sección crítica

– Deadlock (abrazo mortal)• P1 solicita y obtiene recurso R1; P2 solicita y obtiene R2. Luego P1 solicita R2, y P2 solicita R1

– Starvation (inhanición) • Es posible que un proceso esperando por un recurso (bloqueado) nunca lo obtenga

Page 10: Concurrencia:  Exclusión Mútua y Sincronización

10

Concurrencia en compartición

• Ejemplo: Múltiples procesos acceden variables compartidas

• Datos compartidos pueden ser leídos o escritos, y las operaciones de escritura debieran ser exclusivas

• Otro problema coherencia de datos

• Ejemplo: suponga que necesitamos mantener a=b

P1 P2

a = a+1 b = 2*b

b = b+1 a = 2*a

Page 11: Concurrencia:  Exclusión Mútua y Sincronización

11

Concurrencia en cooperación mediante comunicación

• Varios procesos trabajan en conjunto para resolver alguna tarea

• Los procesos se comunican explícitamente, por ejemplo mediante el envío de mensajes

• Si toda la comunicación está basada en paso de mensajes, no existe problema de exclusión mútua.

• Sin embargo, puede existir deadlock e inhanición

Page 12: Concurrencia:  Exclusión Mútua y Sincronización

12

Exclusión mútua

• Una visión abstracta de la implementación de EM sería

P1 P2 void P1() void P2(){ { while (true) { while (true) { código antes de la SC código antes de la SC entercritical(Ra); entercritical(Ra); SC; SC; exitcritical(Ra); exitcritical(Ra); código después de la SC código después de la SC } }} }

Page 13: Concurrencia:  Exclusión Mútua y Sincronización

13

Requirimientos para exclusión mútua

• Sólo un proceso puede estar ejecutando su SC

• Un proceso que no se encuentra en su SC no debe interferir con otros procesos que deseen ingresar a la SC

• No se permite que un proceso que desea entrar en su SC espere indefinidamente: No deadlock o inhanición

• Cuando ningún proceso está en su SC, la solicitud de cualquier proceso para ingresar a su SC no debe ser denegada

• No se puede asumir nada respecto de la velocidad relativa y orden en la ejecución de los procesos

• Un proceso permanece en su SC por un tiempo finito

Page 14: Concurrencia:  Exclusión Mútua y Sincronización

14

Exclusión mútua:solución por hardware

• Deshabilitación de Interrupciones– Recordar que un proceso se ejecuta hasta que invoca un llamado al SO o es

interrumpido– Entoces para garantizar EM, el proceso deshabilita las interrupciones justo antes

de entrar en su SC while (true)

{ deshabilitar_interrupciones(); SC habilitar_interrupciones(); }

– Problema 1: habilidad del procesador para hacer context-switch queda limitada– Problema 2: no sirve para multiprocesadores

Page 15: Concurrencia:  Exclusión Mútua y Sincronización

15

EM: solución por hardware

• Instrucciones especiales de máquina – 2 acciones se llevan a cabo en forma atómica, como leer y escribir o leer y probar sobre

una dirección simple de memoria

– Acceso es bloqueado para cualquier otra instrucción

• Test and Set Instruction

boolean testset (int i) {

if (i == 0) {

i = 1;

return true;

}

else {

return false;

}

}

Page 16: Concurrencia:  Exclusión Mútua y Sincronización

16

EM: solución por hardware

• Instrucción Exchange (swap)

void exchange(int register, int memory) {

int temp;

temp = memory;

memory = register;

register = temp;

}

Page 17: Concurrencia:  Exclusión Mútua y Sincronización

17

EM: ejemplo

• parbegin(P(1), P(2),…,P(n)) suspende la ejecución del programa principal e inicia la ejecución concurrente de n procesos con el mismo código, pero diferente parámetro i

• Sólo aquel que encuentra bolt=0 entra. Los otros permanecen en busy-waiting o spin-waiting

Page 18: Concurrencia:  Exclusión Mútua y Sincronización

18

EM por instrucciones de máquina

• Ventajas– Aplicable a cualquier número de procesos y procesadores que comparten

memoria física

– Simple y fácil de verificar

– Puede ser usada con varias SC, cada una controlada por su propia variable

• Desventajas– Busy-waiting consume tiempo de procesador

– Es posible inhanición

– Es posible deadlock si existe prioridades entre los procesos: Suponga dos procesos P1 y P2, con P1 prioridad más baja que P2. Si P1 está en su SC y luego es interrumpido para que P2 entre al procesador, ¿Qué pasaría?

Page 19: Concurrencia:  Exclusión Mútua y Sincronización

19

Soluciones por Software

• Dos procesos, P0 y P1 comparten la variable global turn la cual indica cuál de los procesos puede ingresar a la seción crítica

• Inicialmente turn = 0

• Garantiza exclusión mútua• Problemas

– Alternación estricta de ejecución. – ¿Qué pasaría se P0 falla?– No existe inanición

while (true) { while (turn != 0); sc(); turn = 1; otro_codigo… }

while (true) { while (turn != 1); sc(); turn = 0; otro_codigo… }

P0 P1

Page 20: Concurrencia:  Exclusión Mútua y Sincronización

20

Segundo intento

• El problema con la solución anterior es que almacenamos el nombre del proceso que puede entrar a la SC

• Una nueva posible solución es almacenar el nombre del procesos que está en su SC

• Boolean flag[2]

• Incialmente flag[0] = flag[1] = false

• Si el uno de los procesos falla fuera de su SC, el otro no se bloquea indefinidamente, pero si se bloque dentro de su SC, si.

• Esta solución no satisface el requerimiento de exclusión mútua!!!

while (true) { while (flag[1]); flag[0] = true; sc(); flag[0] = false; otro_codigo… }

while (true) { while (flag[0]); flag[1] = true; sc(); flag[1] = false; otro_codigo… }

Page 21: Concurrencia:  Exclusión Mútua y Sincronización

21

Tercer intento

• El problema más evidente de la solución anterior es que un proceso puede cambiar su estado después que el otro proceso la ha “consultado”, pero antes que el otro haya entrado a su SC

• flag[0] = flag[1] = False

• El requerimiento de exclusión mútua es satisfecho, pero…

• Se puede producir deadlock ¿por qué?

while (true) { flag[0] = true; while (flag[1]); sc(); flag[0] = false; otro_codigo… }

while (true) { flag[1] = true; while (flag[0]); sc(); flag[1] = false; otro_codigo… }

Page 22: Concurrencia:  Exclusión Mútua y Sincronización

22

Cuarta solución

• Considere la siguiente secuencia– P0 pone flag[0] en true– P1 pone flag[1] en true– P0 chequea flag[1]– P1 chequea flag[0]– P0 pone flag[0] en false– P1 pone flag[1] en false– P0 pone flag[0] en true– P1 pone flag[1] en true

while (true) { flag[0] = true; while (flag[1]){ flag[0] = false; flag[0] = true; } sc(); flag[0] = false; otro_código… }

while (true) { flag[1] = true; while (flag[0]){ flag[1] = false; flag[1] = true; } sc(); flag[1] = false; otro_codigo… }

Livelock

Page 23: Concurrencia:  Exclusión Mútua y Sincronización

23

Una solución correcta (algoritmo de Peterson)

• En este algoritmo usamos dos variables globales:– Turn que indica cual proceso podria entrar a la SC y

– flag[] que indica el desea de entrar a la SC

– Inicialmente flag[0] = flag[1] = false

• Esta solución garantiza exclusión mútua

• No produce deadlock

while (true) { flag[0] = true; turn = 1; while (flag[1] && turn == 1); sc(); flag[0] = false; otro_codigo… }

while (true) { flag[1] = true; turn = 0; while (flag[0] && turn == 0); sc(); flag[1] = false; otro_codigo… }

Page 24: Concurrencia:  Exclusión Mútua y Sincronización

24

Semáforos

• Una semáforo es una variable especial usada para que dos o más procesos se señalicen mutuamente

• Un semáforo es una variable entera – Inicializada con un número no negativo

– Sólo dos operaciones acceden al semáforo

– semWait(s) decrementa el semáforo; si el valor resultante es negativo, el proceso se bloquea; sino, continúa su ejecución

– semSignal(s) incrementa el semáforo; si el valor resultante es menor o igual que zero, entonces se despierta un proceso que fue bloqueado por semWait()

Page 25: Concurrencia:  Exclusión Mútua y Sincronización

25

Primitivas sobre semáforos

Page 26: Concurrencia:  Exclusión Mútua y Sincronización

26

Semáforo binario

• semWait(s) { if (s.value == 1) s.value = 0; else { place this process in s.queue block this process } }

• semSignal(s) { if (s.queue is empty()) s.value = 1 else { remove a process P from s.queue; place P on the ready list; }

• un semáforo binario puede ser inicializado en 0 ó 1

• también son conocidos como mutex

Page 27: Concurrencia:  Exclusión Mútua y Sincronización

27

Exclusión mútua usando semáforos binarios

Page 28: Concurrencia:  Exclusión Mútua y Sincronización

28

Page 29: Concurrencia:  Exclusión Mútua y Sincronización

29

Políticas de encolamiento definequién, entre aquellos que estánesperando, pasa a ejecutarse.

semáforo fuerteGarantiza libre de inhaniciónEj: FIFO

Semáforo débilNo garantiza libre de inhaniciónEj: Prioridad

Page 30: Concurrencia:  Exclusión Mútua y Sincronización

30

El problema del Productor/Consumidor

• Uno o más productores generan datos y lo colocan en un buffer (compartido)

• Un consumidor toma (consume) los datos del buffer uno a la vez

• Sólo un agente (productor o consumidor) accesa el buffer a la vez

Page 31: Concurrencia:  Exclusión Mútua y Sincronización

31

Caso buffer infinito

producer:

while (true) {

/* produce item v */

b[in] = v;

in++;

}

consumer:

while (true) {

while (in <= out)

/*do nothing */;

w = b[out];

out++;

/* consume item w */

}

Page 32: Concurrencia:  Exclusión Mútua y Sincronización

32

Caso buffer circular o finito

producer:

while (true) {

/* produce item v */

while ((in + 1) % n == out)

/* do nothing */;

b[in] = v;

in = (in + 1) % n

}

consumer:

while (true) {

while (in == out)

/* do nothing */;

w = b[out];

out = (out + 1) % n;

/* consume item w */

}

Page 33: Concurrencia:  Exclusión Mútua y Sincronización

33

Page 34: Concurrencia:  Exclusión Mútua y Sincronización

34

•Semáforo binario s es usado para asegurar exclusión mútua

•Semáforo delay se usa para hacer que el consumidor espere si el buffer está vacio

• Variable n = in-out

Solución incorrecta

Page 35: Concurrencia:  Exclusión Mútua y Sincronización

35

Solución correcta

Page 36: Concurrencia:  Exclusión Mútua y Sincronización

36

Solución caso buffer infinito con semáforo contador

Page 37: Concurrencia:  Exclusión Mútua y Sincronización

37

Solución caso buffer finitocon semáforo contador

Semáforo e usado paracontar el número de espaciosvacíos

BloquearseProductor desea insertar en buffer llenoConsumidor desea sacar de buffer vacío

DesbloquearseConsumidor: item insertadoProductor: item sacado

Page 38: Concurrencia:  Exclusión Mútua y Sincronización

38

Implementación de semáforos con testset()

• semWait(s) {

while (!testset(s.flag)) ;

s.count--;

if (s.count < 0) {

place this process in s.queue

block this process and set s.flag to 0

} else (NOOOOO)

s.flag = 0;

• semSignal(s) {

while (!testset(s.flag));

s.count++;

if (s.count <= 0) {

remove a process P from s.queue;

place P on ready list;

}

s.flag = 0;

El SO debe garantizar que la operaciones sobre semáforosse realicen en forma atómica

En este caso la deshabilitación de interrupciones sería una opción válida

Page 39: Concurrencia:  Exclusión Mútua y Sincronización

39

El problema de los filósofos comensales

• Cinco filósofos se sientan alrededor de una mesa con una fuente de spaghetti.

• Cuando un filósofo no está comiendo, está filosofando.• Como carecen de habilidades manuales, necesitan de dos tenedores para

comer, pero sólo hay cinco.• Cuando uno o dos de los tenedores están siendo ocupados por el filósofo de

al lado, el filósofo vuelve a filosofar.• Cuando un filósofo deja de comer spaghetti, coloca los tenedores sobre la

mesa.

Page 40: Concurrencia:  Exclusión Mútua y Sincronización

40

Solución 1

• Esta solución no está libre de deadlock

Semaphore fork[5] = {1}void philosopher(int i) { while (true) { think(); semWait(fork[i]); semWait(fork[(i+1)mod 5]); eat(); semSignal(fork[(i+1] mod 5); semSignal(fork[i]); }}

main(){ parbegin(philosopher(0),philosopher(1), philosopher(2),philosopher(3), philosopher(4));

}

Page 41: Concurrencia:  Exclusión Mútua y Sincronización

41

Solución 2• Una posible solución al problema de deadlock es controlar que sólo 4

tenedores puedan ser usados

Semaphore fork[5] = {1}Semaphore room = 4;void philosopher(int i) { while (true) { think(); semWait(room); semWait(fork[i]); semWait(fork[(i+1)mod 5]); eat(); semSignal(fork[(i+1] mod 5); semSignal(fork[i]); semSignal(room); }}

main(){ parbegin(philosopher(0),philosopher(1), philosopher(2),philosopher(3), philosopher(4));

}

Page 42: Concurrencia:  Exclusión Mútua y Sincronización

42

El problema de los lectores/escritores

• Uno o más lectores pueden estar simultáneamente leyendo un archivo

• Pero sólo un escritor puede estar escribiendo el archivo

• Si un escritor está escribiendo el archivo, ningún lector puede estar leyendo el archivo

• Ej: sistema de biblioteca

• Note que: se garantiza que los lectores sólo leen

• Si lectores y escritores leyeran y escribieran, volveriamos al problema general de exclusión mútua

Page 43: Concurrencia:  Exclusión Mútua y Sincronización

43

Lectores tienenPrioridad

Escritores puede entrar en inanición

Page 44: Concurrencia:  Exclusión Mútua y Sincronización

44

Escritores tienen prioridad,

Escritores tienen prioridad, es decir una vez que un escritor declara su deseo de entrar, no se permite que ningún nuevo lector entre

Page 45: Concurrencia:  Exclusión Mútua y Sincronización

45

Problema típico con semáforos

• ¿Qué pasaría si el programador se equivoca usando las funciones semWait() y semSignal() en el consumidor?

n = 0s = 1void consumer(){ while (true) { semSignal(s); semWait(s); take(); senWait(n); }}

void producer(){ while (true) { produce(); semWait(s); append(); semSignal(s) senWait(n); }}

Page 46: Concurrencia:  Exclusión Mútua y Sincronización

46

Monitores

• Un monitor es un módulo de software que evita errores de programación

• Carácterísticas principales:– Variables locales son accesadas sólo dentro del monitor; es decir por la

funciones del monitor

– Para ingresar al monitor, un proceso invoca algunas de las funciones del monitor

– Sólo un proceso puede estar ejecutándose en el monitor => exclusión mútua

• Los monitores necesitan usar variables de condición:– Suponga que un proceso dentro del monitor necesita suspenderse hasta que una

condición se haga verdadera

– Las variables de condición proveen el mecanismo de sincronización para suspender un proceso dentro del monitor y reanudar su ejecución en otro momento

Page 47: Concurrencia:  Exclusión Mútua y Sincronización

47

Variables de condición

• cwait(c): suspende la ejecución del proceso llamador en la variable de condición c. El monitor queda libre para ser usado por otro proceso

• csignal(c): resume la ejecución de algún proceso bloqueado por un cwait() sobre la misma variable c. Si hay varios procesos bloqueados, elegir cualquiera; si no hay ninguno bloqueado, no hacer nada

• Note que las funciones cwait() y csignal() se parecen a semWait() y semSignal(), PERO NO son iguales y cumplen una función distinta

Page 48: Concurrencia:  Exclusión Mútua y Sincronización

48

Page 49: Concurrencia:  Exclusión Mútua y Sincronización

49

Solución al problema productor/consumidor con monitor

notfull v.c. para dormir el productor cuando buffer está llenonotempty v.c. para dormir al consumidor cuando el buffer está vacío

Page 50: Concurrencia:  Exclusión Mútua y Sincronización

50

Solución (continuación)

Page 51: Concurrencia:  Exclusión Mútua y Sincronización

51

Solución al problema de los filósofos con monitores

Monitor dinning_philosophersstate[5] of {THINKING, HUNGRY, EATING};Cond self[5];

void get_forks(int i) { state[i] = HUNGRY; test(i); if (state[i] != EATING then cwait(self[i]);}void put_forks(int i) { state[i] = THINKING; test((i+4) mod 5); test((i+1) mod 5);}void test(int i) { if (state[i+4 mod 5] != EATING && state[i] == HUNGRY && state[i+1 mod 5] != EATING) { state[i] = EATING; csignal(self[i]); }}

Void philosopher(int i){ while (true) { think(); get_forks(i); eat(); put_forks(i); }}

void main() { state[0] = state[1] =… THINKING parbegin(philosopher(0),... )}

Page 52: Concurrencia:  Exclusión Mútua y Sincronización

52

Paso de Mensajes

• Los mecanismos de sincronización que hemos visto hasta ahora están basados en variables compartidas (globales), es decir la comunicación es implícita

• El paso de mensajes es un mecanismo de sincronización donde la comunicación es explícita.

• Paso de mensajes significa que un proceso envía información a otro proceso con el cual no comparten memoria

• Dos primitivas básicas

send (destination, message)

receive (source, message)

Page 53: Concurrencia:  Exclusión Mútua y Sincronización

53

Sincronización

• El paso de mensajes implica necesariamente un nivel básico de sincronización: el receptor de la información no puede recibirla antes que el enviador la envíe.

• Blocking send, blocking receive– Tanto el enviador como el receptor se bloquean hasta que el mensaje llegue al

receptor

• Nonblocking send, blocking receive– El enviador continúa su ejecución después de enviarla

– El receptor se bloquea hasta que llegue

• Nonblocking send, nonblocking receive– Ninguno se bloquea

Page 54: Concurrencia:  Exclusión Mútua y Sincronización

54

Direccionamiento

• Direccionamiento directo– La primitiva send() incluye el identificador del proceso destino

– La primitiva receive() podría (o no) saber quien le envía el mensaje y tomaria la información del mensaje fuente

– Asi, podría enviar una confirmación de recepción del mesaje

• Direccionamiento indirecto– Los mensajes no se envia de un proceso a otro, sino a una estructura de datos

compartida consistente de colas que almacenan temporalmente mensajes

– Mailboxes

– Asi, un proceso deposita un mensaje en el mailbox y otro lo recupera

– Permite tener más modelos de comuniucación, como se presenta a continuación

Page 55: Concurrencia:  Exclusión Mútua y Sincronización

55

Page 56: Concurrencia:  Exclusión Mútua y Sincronización

56

Formato de mensaje

Page 57: Concurrencia:  Exclusión Mútua y Sincronización

57

Exclusión mútua con paso de mensajes• Asumimos blocking receive() y nonbloquing send()

• Se crea un “mailbox” mutex

• Para entrar a la SC, un proceso debe recibir un mensaje

• Cuando sale de la SC pone devuelta el mensaje en el mailbox

• Asumimos si dos o más procesos hacen un receive() al mismo tiempo, sólo uno de ellos lo recibe

Page 58: Concurrencia:  Exclusión Mútua y Sincronización

58

Solución al problema del productor/consumidor