You are on page 1of 24

Semforos

Cecilia Hernndez 2013

Semforos

Primitiva de Sincronizacin propuesta por Dijkstra en 1968


Como parte de sistema THE Usados para exclusin mutua y planificacin De nivel ms alto que locks Wait(semaforo)
Decrementa semforo Bloquea hebra/proceso si el semforo es menor que cero, sino entonces permite a hebra/proceso continuar Operacion tambien llamada P(semaforo) o down(semaforo)

Variable atmica manipulada por dos operaciones

Signal(semforo)
Incrementa semforo en uno y si hay algn proceso/hebra esperando lo despierta Tambin llamada V(semaforo) o up(semaforo)

Valor de semforo puede ser mayor que 1


Inicializado en 1 es como lock.
Usado para exclusin mutua

Inicializado en N
Usado como contador atmico

Implementacin de Semforos
typedef struct { int value; struct hebra *L; } semaphore; void wait(semaphore S) { S.value--; if (S.value < 0){ agregar hebra a S.L; block(); } } void signal(semaphore S){ S.value++; if (S.value <= 0){ remover hebra T de S.L; wakeup(T); } }

Exclusin mutua vs planificacin


Exclusin mutua - Slo una hebra a la vez en SC - Puede ser cualquier hebra lock Seccin crtica unlock

Planificacin - Requerimiento de orden en ejecucin de hebras.

tiempo

Ejemplo planificacin

tiempo H1. imprime A

sem S1 = 0, S2 = 0 H1: H2: print A; wait(S1); signal(S1); print B; signal(S2);

H3: wait(S2); print C;

H2. imprime B H3. imprime C

Tipos de Semforos

Binarios (mutex) Garantizan exclusin mutua a recurso Slo una hebra/proceso puede accesar seccin crtica a la vez Contador de semforo inicializado en 1 Contadores Representan recursos con ms de una unidad disponible Permiten accesar recursos de acuerdo al nmero de recursos disponibles Contador es inicializado en N, donde N es la cantidad de unidades disponibles del recurso

Ejemplos Clsicos de Sincronizacin

Problema Productor/Consumidor

Un buffer en memoria con N slots disponibles


Necesita llevar cuenta de temes en buffer

Productor produce temes a ingresar al buffer Consumidor consume temes del buffer
C

Productor Agrega item usando puntero in out in

Consumidor Remueve item usando puntero out

Algoritmo Productor/Consumidor
int contador = 0; //indica nmero de items en buffer Tipo buffer[N]; int in = 0; int out = 0; Productor while (true) { /* produce un item en proxProd */ while (contador == N); //espera buffer[in] = proxProd; in = (in + 1) % N; contador++; } Consumidor while (true) { while (contador == 0); //espera proxCons = buffer[out]; out = (out + 1) % N; contador--; /* consume prodCons */ }

Cmo resolver problema?

Identificar restricciones inherentes al problema


Estado

compartido?

contador (consumidores y productores) Buffer


in ( productores) . Productores no pueden insertar en buffer lleno out ( consumidores). Consumidores no pueden extraer de buffer vaco

Posible resolver con locks? Si Posible resolver con semforos? Si

Cmo resolver problema?

Identificar estado compartido y restricciones de problema


Buffer de tamao limitado compartido entre productores y consumidores Productor escribe en buffer[in], in indica posicin de escritura en buffer Consumidor extrae de buffer[out], out indica posicin de extraccin de buffer Contador indica el nmero de elementos actuales en el buffer Mltiples productores deben manipular in, buffer[in] y contador atmicamente. Mltiples consumidores deben manipular out, buffer[out] y contador atmicamente Mltiples consumidores y productores deben manejar contador atmicamente

Solucin Productor/Consumidor usando locks


int contador = 0; //indica nmero de items en buffer char buffer[N]; int in = 0; int out = 0; lock_t mutex; Consumidor Productor while (true) { /* produce un item en proxProd */ lock(mutex); while(contador == N){ unlock(mutex); yield(); lock(mutex); } buffer[in] = proxProd; in = (in + 1) % N; contador++; unlock(mutex); } While(true){ lock(mutex); while(contador == 0){ unlock(mutex); yield(); lock(mutex); } proxCons = buffer[out]; out = (out + 1) % N; contador--; unlock(mutex); /* consume proxCons */ }

Solucin usando semforos

Identificar estado compartido y restricciones de problema

Ya presentadas Cuando buffer est lleno productores deben esperar a que exista una posicin vaca (generada por un consumidor) Cuando buffer esta vaco consumidores deben esperar a que exista un elemento en el buffer (generado por un productor) Acceso a buffer y contador debe realizarse atmicamente Mutex (inicializado en 1): para exclusin mutua de buffer, in, out y contador. Full (inicializado en 0). Para indicar cuntas posiciones llenas hay en el buffer Empty (inicializado en N). Para indicar cuantas posiciones vacas hay en el buffer

Especificar condiciones de espera y sealizacin


Identificar semforos para proveer sincronizacin


Proporcionar algoritmos

Solucin usando semforos


int contador = 0; //indica nmero de items en buffer char buffer[N]; int in = 0; int out = 0; sem mutex=1; sem vacio = N; sem lleno = 0; Productor while (true) { /* produce un item en proxProd */ wait(vacio); wait(mutex); buffer[in] = proxProd; in = (in + 1) % N; contador++; signal(mutex); signal(lleno); } Consumidor While(true){ wait(lleno); wait(mutex); proxCons = buffer[out]; out = (out + 1) % N; contador--; signal(mutex); signal(vacio); /* consume proxCons */ }

Ejemplos

Productor/consumidor usando pthreads y locks Productor/consumidor usando pthreads y semforos

http://www.inf.udec.cl/~chernand/so/ejemplos/prodconsLocks.cpp

http://www.inf.udec.cl/~chernand/so/ejemplos/prodconsSem.cpp

Problema lectores/escritor

Caso base de datos


Varios

lectores pueden accesar registro datos simultaneamente Slo un escritor puede escribir

L E Registro BD L

Cmo resolver problema?

Identificar estado compartido y restricciones de problema

Base de datos compartida


Mientras haya un lector un escritor no puede accesar base de datos Mientras exista un escritor en base de datos ningn otro escritor o lector puede accesarla

Identificar condiciones de espera y sealizacin


Si existe un escritor en BD otro escritor o lector debe esperar Cuando un escritor termina debe sealizar escritor o lector que espera Si podemos tener varios lectores debemos contarlos, para saber cuando existe uno
Si hay uno leyendo y llegan otros, otros tambien pueden leer Si solo hay uno y sale puede haber un escritor esperando accesar BD

Qu semforos necesitamos

Uno inicializado en 1 como mutex para manejar contador de lectores Uno tipo mutex para escritor y primer lector

Algoritmo usando semforos


sem mutex=1; sem escribir = 1; Int contadorLectores = 0; Escritor: wait(escribir); espera por escritor o lector Escritor_escribe; Escribe objeto signal(escribir); permite leer y/o escribir a otros, escritura completada Lector: wait(mutex); asegura acceso exclusivo a contador de lectores contadorLectores++; incrementa lectores if(contadorLectores == 1) then wait(escribir); Si es el primer lector espera si hay escritor signal(mutex); Lector_lee; wait(mutex); asegura acceso exclusivo a contador de lectores contadorLectores--; lector termin de leer if(contadorLectores == 0) then signal(escribir); no mas lectores por si escritor esperaba signal(mutex)

Notas sobre Lectores/Escritores

Primer lector se bloquea si hay un escritor activo cualquier otro escritor se bloquea tambin Si un escritor espera porque existen lectores activos, el ltimo lector lo despierta cuando sale pueden otros lectores entrar cuando el escritor est esperando? Cuando un escritor sale, si hay un escritor y un lector esperando quien entra?

Otro ejemplo clsico

Problema de Filsofos comensales


Cada filsofo tiene su plato de arroz, con 5 palitos 5 filsofos se sientan a la mesa. Piensan por un rato y cuando les da hambre comen Hay slo 5 palitos en la mesa (cada persona necesita 2 palitos para comer arroz a la manera china) Para poder comer cada filsofo tiene que obligatoriamente conseguir dos palitos

Problema es importante porque introduce posibles problemas de Deadlock(bloqueo mortal) y Starvation(inanicin)

Problema de Filsofos comensales

Problemas que pueden surgir con mala sincronizacin

Deadlock Hebras/Procesos estn en deadlock cuando


2 o ms hebras o procesos estn esperando por una condicin que slo puede ser causada por una hebra que tambien est esperando. Puede darse con 2 o ms hebras en la lista de espera de un mismo semforo?

Starvation o espera indefinida Hebras/Procesos esperan indefinidamente para poder accesar un recurso.
Ejemplo, una hebra en la lista de espera de un semforo de la cual estn entrando y saliendo continuamente hebras y la lista de espera de semforo es LIFO

Ejemplo deadlock con productor/consumidor


int contador = 0; //indica nmero de items en buffer char buffer[N]; int in = 0; int out = 0; sem mutex=1; sem vacio = N; sem lleno = 0; Productor while (true) { /* produce un item en proxProd */ wait(mutex); wait(vacio); buffer[in] = proxProd; in = (in + 1) % N; contador++; signal(mutex); signal(lleno); } Que sucede aqu? Consumidor While(true){ wait(lleno); wait(mutex); proxCons = buffer[out]; out = (out + 1) % N; contador--; signal(mutex); signal(vacio); /* consume proxCons */ }

Problemas con Semforos

A pesar que se pueden usar para resolver cualquier problema de sincronizacin Son variables globales por lo tanto pueden ser accesadas de cualquier hebra directamente
no es buena tcnica de ingeniera de software

No hay conexin entre el semforo y el recurso para el cual se quiere controlar acceso Usados como mutex (ingreso a seccin crtica) y para coordinacin (planificacin, eleccin quien tiene acceso al recurso) No se puede controlar su uso, no hay garanta que el programador los use adecuadamente (fcil de cometer errores)

Resumen

Semforos primitivas de sincronizacin de ms alto nivel que locks No relacin entre semforo y recurso que controla Fcil de cometer errores que pueden producir deadlock y starvation
Importante

entender bien problema antes de

utilizarlos

Prxima semana Monitores