Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Cecilia Hernández
2007-1
Semáforos
Primitiva de Sincronización propuesta por Dijkstra en 1968
Como parte de sistema THE
Usados para exclusión mutua y planificación
De nivel más alto que locks
Variable atómica manipulada por dos operaciones
Wait(semaforo)
• Decrementa semáforo
• Bloquea hebra/proceso si el semáforo es menor que cero, sino
entonces permite a hebra/proceso continuar
• Operacion tambien llamada P(semaforo) o down(semaforo)
Signal(semáforo)
• Incrementa semáforo en uno y si hay algún proceso/hebra
esperando lo despierta
• También llamada V(semaforo) o up(semaforo)
Valor de semáforo puede ser mayor que 1
• Inicializado en 1 es como lock.
• Usado para exclusión mutua
• Inicializado en N
• Usado como contador atómico
Implementación de Semáforos
typedef struct {
int value;
struct hebra *L;
} semaphore;
void wait(semaphore S) {
S.value--;
if (S.value < 0){
agregar hebra a S.L;
block();
}
}
Exclusión mutua
- Sólo una hebra a lock
la vez en SC Sección crítica
- Puede ser unlock
cualquier hebra
Planificación
- Requerimiento de
orden en ejecución de
hebras.
tiempo
Ejemplo planificación
tiempo
H1. imprime A
sem S1 = 0, S2 = 0 H2. imprime B
H1: H2: H3:
print A; wait(S1); wait(S2); H3. imprime C
signal(S1); print B; print C;
signal(S2);
Tipos de Semáforos
Binarios (mutex)
Garantizan exclusión mutua a recurso
Sólo una hebra/proceso puede accesar sección crítica a
la vez
Contador de semáforo inicializado en 1
Contadores
Representan recursos con más de una unidad disponible
Permiten accesar recursos de acuerdo al número de
recursos disponibles
Contador es inicializado en N, donde N es la cantidad de
unidades disponibles del recurso
Ejemplos Clásicos de Sincronización
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
P C
Productor Consumidor
Agrega item Remueve item
usando puntero in usando puntero
out
out in
Algoritmo Productor/Consumidor
Productor Consumidor
Productor Consumidor
while (true) {
/* produce un item en proxProd */ While(true){
lock(mutex); lock(mutex);
while(contador == N){ while(contador == 0){
unlock(mutex); unlock(mutex);
yield(); yield();
} }
buffer[in] = proxProd; proxCons = buffer[out];
in = (in + 1) % N; out = (out + 1) % N;
contador++; contador--;
unlock(lock); unlock(mutex);
} /* consume proxCons */
}
Solución usando semáforos
Productor Consumidor
while (true) {
/* produce un item en proxProd */ While(true){
wait(vacio); wait(lleno);
wait(mutex); wait(mutex);
buffer[in] = proxProd; proxCons = buffer[out];
in = (in + 1) % N; out = (out + 1) % N;
contador++; contador--;
signal(mutex); signal(mutex);
signal(lleno); signal(vacio);
} /* consume proxCons */
}
Ejemplos
Productor/consumidor usando
pthreads y locks
http://www.inf.udec.cl/~chernand/sc/ej
emplos/prodconsLocks.C
Productor/consumidor usando
pthreads y semáforos
http://www.inf.udec.cl/~chernand/sc/ej
emplos/prodconsSem.C
Problema lectores/escritor
L
E
Registro BD
L
Cómo 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 ningún otro escritor
o lector puede accesarla
Identificar condiciones de espera y señalización
Si existe un escritor en BD otro escritor o lector debe esperar
Cuando un escritor termina debe señalizar 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é semáforos necesitamos
Uno inicializado en 1 como mutex para manejar contador de
lectores
Uno tipo mutex para escritor y primer lector
Algoritmo usando semáforos
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 = 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 = contadorLectores--; lector terminó de leer
if(contadorLectores == 0) then signal(escribir); no mas lectores por si escritor
esperaba
signal(mutex)
Notas sobre Lectores/Escritores
Productor Consumidor
while (true) {
/* produce un item en proxProd */ While(true){
wait(mutex); wait(lleno);
wait(vacio); wait(mutex);
buffer[in] = proxProd; proxCons = buffer[out];
in = (in + 1) % N; out = (out + 1) % N;
contador++; contador--;
signal(mutex); signal(mutex);
signal(lleno); signal(vacio);
} /* consume proxCons */
Que sucede aquí? }
Problemas con Semáforos