Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 2
Productor-consumidor
Un proceso produce datos que son posteriormente
procesados por otro proceso
i.e.: el manejador de teclado y el programa que
recoge los caracteres de un buffer
Lo más cómodo es emplear un buffer circular
Escribe Lee
Productor Consumidor
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 3
Código del productor
El productor no puede escribir en el buffer si está lleno
Comparte con el consumidor: el buffer y el contador
do {
...
produce un nuevo elemento (elemento_p)
...
while (contador == MAX_ELEMENTOS)
haz_nada;
buffer[indice_p] = elemento_p;
indice_p = (indice_p + 1) %
MAX_ELEMENTOS;
contador = contador + 1;
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 4
Código del consumidor
El consumidor no puede leer del buffer si está vacío
Comparte con el productor: el buffer y el contador
do {
while (contador == 0) haz_nada;
elemento_c = buffer[indice_c];
indice_c = (indice_c + 1) %
MAX_ELEMENTOS;
contador = contador - 1;
...
consume el elemento (elemento_c)
...
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 5
Condiciones de carrera
El código anterior no funciona por existir
condiciones de carrera al actualizar el contador
Veamos qué ocurre al ejecutar la sentencia:
contador = contador + 1;
Productor Consumidor
load r0, contador load r0, contador
add r0, 1 sub r0, 1
store contador, r0 store contador, r0
Problema: la modificación del contador no es
atómica
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 6
Atomicidad
Una operación se dice que es atómica (en un
sistema uniprocesador) cuando se ejecuta con las
interrupciones deshabilitadas
Las referencias y las asignaciones son atómicas en
la mayoría de los sistemas. Esto no es siempre
cierto para matrices, estructuras o números en
coma flotante
Si el HW no proporciona operaciones atómicas,
éstas no pueden construirse por SW
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 7
Sincronización
Persona B
Persona A
3:00 Mira en la nevera. No hay leche
3:05 Va a la tienda
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 9
Problema de la sección crítica
Toda solución debe cumplir tres condiciones
Exclusión mutua
Progreso
Espera limitada
Solución general:
do {
protocolo de entrada
sección crítica
protocolo de salida
resto de la sección
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 10
Tipos de soluciones
Suposiciones:
Los procesos se ejecutan a una velocidad 0
Su velocidad relativa no influye
Soluciones basadas en variables de control
Soluciones basadas en instrucciones máquina
específicas (test-and-set o swap)
Soluciones basadas en primitivas del SO
Soluciones basadas en regiones críticas y
monitores
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 11
Solución con variables de control
Válidas para varios procesadores
Suposición: las instrucciones de carga y
almacenamiento son atómicas
Primer intento
Ti y Tj comparten la variable turno
Thread Ti
do {
while (turno != i) haz_nada;
sección crítica
turno = j;
resto de la sección
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 12
Segundo intento
Variables compartidas:
flag[i] = FALSE;
flag[j] = FALSE;
Estas variables indican la intención de los hilos de entrar
en sección crítica
Thread Ti
do {
flag[i] = TRUE;
while (flag[j]) haz_nada;
sección crítica
flag[i] = FALSE;
resto de la sección
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 13
Tercer intento (Dekker)
Variables compartidas:
int turno, flag[2];
flag[i] = flag[j] = FALSE;
Thread Ti
do {
flag[i] = TRUE;
turno = j;
while (flag[j] && (turno == j))
haz_nada;
sección crítica
flag[i] = FALSE;
resto de la sección
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 14
Sincronización hardware
int test_and_set (int *destino) {
int aux;
aux = *destino;
*destino = TRUE;
return (aux); }
Variable compartida cerrojo iniciada a FALSE
do {
while (test_and_set (&cerrojo))
haz_nada;
sección crítica
cerrojo = FALSE;
resto de la sección
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 15
Instrucción swap
void swap (int *a, int *b) {
int aux;
aux = *a;
*a = *b;
*b = aux; }
Variable compartida cerrojo iniciada a FALSE
do { llave = TRUE;
do {
swap (cerrojo, llave);
} while (llave != FALSE);
sección crítica
cerrojo = FALSE;
resto de la sección
} while (TRUE);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 16
Semáforos
Introducidos por Dijkstra en los años 60
Es un tipo especial de variable que sólo puede ser
accedida por dos primitivas P y V
P (semáforo): operación atómica que espera
hasta que la variable semáforo sea positiva, en este
momento la decrementa en 1
V (semáforo): operación atómica que incrementa
la variable semáforo en 1
¿Cómo quedaría el problema de la sección crítica
con semáforos?
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 17
Características de los semáforos
Son independientes de la máquina
Son simples
Pueden trabajar con varios procesos
Pueden permitir que varios procesos entren en la
sección crítica al mismo tiempo en caso de
necesitarse esta posibilidad
Doble uso de los semáforos:
Exclusión mutua
Sincronización
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 18
Productor-consumidor
Restricciones:
El consumidor espera a que haya datos en el buffer
El productor espera a que haya buffers vacíos
Sólo un único proceso puede manipular el buffer a la
vez
Semáforos:
smf_llenos, smf_vacíos y exmut
Inicialización:
smf_llenos = 0
smf_vacíos = número_de_buffers
exmut = 1
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 19
Productor Consumidor
P (smf_vacíos); P (smf_llenos);
P (exmut); P (exmut);
Produce un dato; Consume el dato;
V (exmut); V (exmut);
V (smf_llenos); V (smf_vacíos);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 21
Iniciación
leer = escribir = 0
exmut = 1
LA = EA = LE = EE = 0
Además:
Los escritores tienen prioridad sobre los lectores
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 22
Lector Escritor
P (exmut); P (exmut);
if ((EA + EE) == 0) { if (( EA + LA + EE) == 0){
V (escribir);
V (leer); EA = EA + 1;
LA = LA + 1; } else {
} else { EE = EE + 1;
LE = LE + 1; }
V (exmut);
} P (escribir);
V (exmut); Escribimos los datos;
P (leer); P (exmut);
Leemos los datos; EA = EA - 1;
if (EE > 0) {
P (exmut); V (escribir);
LA = LA - 1; EA = EA + 1;
if (LA == 0 && EE > 0) { EE = EE - 1;
V (escribir); } else while (LE > 0) {
V (leer);
EA = EA + 1; LA = LA + 1;
EE = EE - 1; LE = LE - 1;
} }
V (exmut); V (exmut);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 23
Casos particulares
Un lector entra y deja el sistema
Un escritor entra y deja el sistema
Entran dos lectores al sistema
Un escritor entra y debe esperar
Un lector entra y debe esperar
Los lectores abandonan el sistema y el escritor
continúa
Los escritores abandonan el sistema, y el último
lector continúa y abandona
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 24
Problema de los filósofos
Variables compartidas:
exmut
semaforo[N]
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 25
Problema de los filósofos
void toma_tenedores(int i) {
P(exmut);
estado[i] = HAMBRIENTO;
comprueba(i);
V(exmut);
P(semaforo[i]);
} /* Fin de toma_tenedores */
void pon_tenedores(int i) {
P(exmut);
estado[i] = PENSANDO;
comprueba((i-1)%N);
comprueba((i+1)%N);
V(exmut);
} /* Fin de pon_tenedores */
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 26
Problema de los filósofos
void comprueba(int i) {
if (estado[i] == HAMBRIENTO
&& estado[(i-1)%N] != COMIENDO
&& estado[(i+1)%N] != COMIENDO)
{
estado[i] = COMIENDO;
V(semaforo[i]);
}
} /* Fin de comprueba */
¿A qué valores se deben iniciar los semáforos?
¿Por qué la función comprueba siempre se invoca
desde una sección crítica?
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 27
Problema del barbero dormilón
Problema: 1 barbero y N sillas de espera
Si un cliente entra y no hay sillas, se va
Semáforos:
clientes: número de clientes en espera sin
contar el que está en la silla del peluquero
barberos: número de barberos inactivos
exmut: exclusión mutua
Variable compartida:
esperando: número de clientes esperando
Inicialmente:
clientes=0 barberos=0 exmut=1 esperando=0
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 28
Barbero Cliente
do { do {
P(clientes); P(exmut);
P(exmut); if (esperando < SILLAS) {
esperando=esperando-1; esperando=esperando + 1;
V(barberos); V(clientes);
V(exmut); V(exmut);
P(barberos);
/* Se corta el pelo */
/* Corta el pelo */
} else {
V(exmut);
} while (TRUE);
}
} while (PELOLARGO);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 29
Problema del puente estrecho
Por un puente sólo pueden pasar o coches que
suben o coches que bajan.
Solución:
Variables compartidas:
int contadorsubida = 0, contadorbajada = 0;
semaforo exmut_s, exmut_b, puente;
Iniciación:
Los semáforos inicialmente deben valer 1
No se tratan los problemas de inanición
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 30
Código subida Código bajada
P(exmut_s); P(exmut_b);
contadorsubida++; contadorbajada++;
if (contadorsubida == 1) if (contadorbajada == 1)
P(puente); P(puente);
V(exmut_s); V(exmut_b);
P(exmut_s); P(exmut_b);
contadorsubida--; contadorbajada--;
if (contadorsubida == 0) if (contadorbajada == 0)
V(puente);
V(puente);
V(exmut_b);
V(exmut_s);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 31
Codificación los semáforos
Las primitivas P y V se realizan por SW
Razón: P y V se ven implicados en aspectos de
planificación
Partimos de la siguiente declaración:
typedef struct {
int contador;
(cola q;)
int t; /* Para multiprocesadores
*/
} SEMAFORO;
En el caso de los semáforos con espera activa el
código entre paréntesis sobra
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 32
P y V en spin locks (espera activa)
P (SEMAFORO *s) { V (SEMAFORO *s) {
while (1) { cli;
cli; s->contador+ = 1;
if (s->contador > 0) sti;
{ }
s->contador- = 1;
sti;
return;
}
sti;
} /* fin del while */
}
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 33
P y V en sistemas uniprocesador
P (SEMAFORO *s) { V (SEMAFORO *s) {
cli; cli;
if (s->contador > 0) if (s->q == vacía) {
{ s->contador+ = 1;
s->contador- = 1; } else {
sti; Sacar proceso de s-
return; >q
} Despertarlo
Añadimos proc. a s->q }
sti; sti;
Planificación }
}
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 34
P y V en sistemas multiprocesador
P (SEMAFORO *s) { V (SEMAFORO *s) {
while (TAS(s->t) != 0); while (TAS(s->t) != 0);
if (s->contador > 0) { if (s->q vacía) {
s->contador- = 1; s->contador+ = 1;
s->t = 0; } else {
return; Sacar proceso de s-
} >q;
Añadimos proc. a s->q Despertarlo;
s->t = 0; }
Planificación s->t = 0;
} }
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 35
Comunicación con mensajes
Válido para comunicación intermáquina
Definición:
Mensaje: parte de información que es pasada de
un proceso a otro
Buzón: lugar donde se depositan los mensajes
desde el envío a la recepción
Operaciones sobre mensajes:
Enviar
Recibir
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 36
Métodos de comunicación
Comunicación en un único sentido: los mensajes
fluyen en un único sentido
Ejemplos: Tuberías de UNIX, productor-
consumidor y streams
Comunicación bidireccional: los mensajes fluyen en
ambos sentidos
Ejemplos: Llamadas a procedimientos remotos
(RPC´s) o el modelo cliente-servidor
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 37
Ejemplos
Productor: Consumidor:
int mensaje1[1000]; int mensaje2[1000];
while (1) { while (1) {
--Preparamos el recibir (mensaje2,
mensaje1-- buzón);
enviar (mensaje1, --Procesamos el
buzón); mensaje2--
} }
Cliente: Servidor:
char resp[1000]; char orden[100];
envia(“leer vax”, char resp[1000];
buzon1); recibir (orden, buzon1);
recibir (resp, buzon2); enviar (resp, buzon2);
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 38
¿Por qué utilizar mensajes?
Muchas aplicaciones responden a este esquema
Las partes que se comunican pueden ser
completamente independientes.
Ventajas:
Es más difícil que se produzcan errores
Permite que los procesos no confíen entre sí
Las aplicaciones pueden ser escritas por
programadores y en tiempos diferentes
Los procesos pueden correr en diferentes
procesadores, conectados a través de una red
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 39
Implementación de los mensajes
Nombres
Comunicación simétrica
Comunicación asimétrica
Copiado
Paso por valor: es lento y obligatorio en sistemas
sin memoria compartida
Paso por referencia: es rápido pero hay
problemas con su modificación
Híbrido: copy-on-write
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 40
Implementación de los mensajes
Bloqueo versus no bloqueo
enviar y recibir pueden ser bloqueantes o no
Formas de espera en un buzón:
Varios procesos pueden esperar en un buzón
Un proceso puede esperar en varios buzones
Longitud
Mensajes de longitud fija
Mensajes de longitud variable
Sincronización de
2009-2010 Mariano Gómez Plaza
procesos 41