La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

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

Presentaciones similares


Presentación del tema: "Concurrencia: Exclusión Mútua y Sincronización"— Transcripción de la presentación:

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

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

3 Concurrencia

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.

5 Un ejemplo simple void echo() { chin = getchar(); // asuma que chin is compartida chout = chin; putchar(chout); } Proceso P 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

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 P P2 b = b + c c = b + c

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

8

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

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 P P2 a = a b = 2*b b = b a = 2*a

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

12 Exclusión mútua Una visión abstracta de la implementación de EM sería
P 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 } } } }

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

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

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;

16 EM: solución por hardware
Instrucción Exchange (swap) void exchange(int register, int memory) { int temp; temp = memory; memory = register; register = temp; }

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

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?

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 P0 P1 while (true) { while (turn != 0); sc(); turn = 1; otro_codigo… } while (true) { while (turn != 1); sc(); turn = 0; otro_codigo… }

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… }

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… }

22 Cuarta solución Livelock Considere la siguiente secuencia
while (true) { flag[1] = true; while (flag[0]){ flag[1] = false; } sc(); otro_codigo… while (true) { flag[0] = true; while (flag[1]){ flag[0] = false; } sc(); otro_código… 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 Livelock

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[1] = true; turn = 0; while (flag[0] && turn == 0); sc(); flag[1] = false; otro_codigo… } while (true) { flag[0] = true; turn = 1; while (flag[1] && turn == 1); sc(); flag[0] = false; otro_codigo… }

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()

25 Primitivas sobre semáforos

26 Semáforo binario un semáforo binario puede ser inicializado en 0 ó 1
semSignal(s) { if (s.queue is empty()) s.value = 1 else { remove a process P from s.queue; place P on the ready list; } semWait(s) { if (s.value == 1) s.value = 0; else { place this process in s.queue block this process } un semáforo binario puede ser inicializado en 0 ó 1 también son conocidos como mutex

27 Exclusión mútua usando semáforos binarios

28

29 Políticas de encolamiento define quién, entre aquellos que están
esperando, pasa a ejecutarse. semáforo fuerte Garantiza libre de inhanición Ej: FIFO Semáforo débil No garantiza libre de inhanición Ej: Prioridad

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

31 Caso buffer infinito consumer: producer: while (true) { while (true) {
while (in <= out) /*do nothing */; w = b[out]; out++; /* consume item w */ } producer: while (true) { /* produce item v */ b[in] = v; in++; }

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 */ }

33

34 Solución incorrecta 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

35 Solución correcta

36 Solución caso buffer infinito con semáforo contador

37 Solución caso buffer finito con semáforo contador
Semáforo e usado para contar el número de espacios vacíos Bloquearse Productor desea insertar en buffer lleno Consumidor desea sacar de buffer vacío Desbloquearse Consumidor: item insertado Productor: item sacado

38 Implementación de semáforos con testset()
El SO debe garantizar que la operaciones sobre semáforos se realicen en forma atómica 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; 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; En este caso la deshabilitación de interrupciones sería una opción válida

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.

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)); Esta solución no está libre de deadlock

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));

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

43 Lectores tienen Prioridad Escritores puede entrar en inanició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

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 = 0 s = 1 void consumer() { while (true) semSignal(s); semWait(s); take(); senWait(n); } void producer() { while (true) produce(); semWait(s); append(); semSignal(s) senWait(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

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

48

49 Solución al problema productor/consumidor con monitor
notfull v.c. para dormir el productor cuando buffer está lleno notempty v.c. para dormir al consumidor cuando el buffer está vacío

50 Solución (continuación)

51 Solución al problema de los filósofos con monitores
Monitor dinning_philosophers state[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),... ) }

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)

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

54 Direccionamiento Direccionamiento directo Direccionamiento indirecto
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

55

56 Formato de mensaje

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

58 Solución al problema del productor/consumidor


Descargar ppt "Concurrencia: Exclusión Mútua y Sincronización"

Presentaciones similares


Anuncios Google