Está en la página 1de 27

Sistemas Operativos

Tema 7: Concurrencia y
Sincronización

1
Índice:
Tema 7: Concurrencia y Sincronización

1. Suspensión y Reanudación

2. Semáforos

3. Propiedades y Características de los


Semáforos

4. Problemas Clásicos de Concurrencia


2
Índice:
Tema 7: Concurrencia y Sincronización

1. Suspensión y Reanudación

2. Semáforos

3. Propiedades y Características de los


Semáforos

4. Problemas Clásicos de Concurrencia


3
1. Suspensión y Reanudación
 Primitivas más simples:
Tema 7: Concurrencia y Sincronización

sleep ()
Bloquea al proceso que la invoca

wakeup (int pid)


Reanuda a proceso cuyo PID se indica
¿Y si dicho proceso no está sleeping?
• La llamada a wakeup() no tiene efecto
• Se recuerda la llamada para que el próximo sleep() que haga
el proceso no tenga efecto.
• Se trata como un error.

4
1. Suspensión y Reanudación
 Implementación: ¡trivial!
Tema 7: Concurrencia y Sincronización

sleep ()
Nuevo estado proceso llamante: bloqueado
Insertar en lista de procesos bloqueados
Activar bit “sleeping” en PCB para indicar causa de
bloqueo

wakeup (int pid)


Nuevo estado proceso despertado: preparado
Quitar de lista de procesos bloqueados e insertar en
preparados
Desactivar bit “sleeping” en PCB

5
1. Suspensión y Reanudación
 Aplicando estas primitivas a resolver problemas en
Tema 7: Concurrencia y Sincronización

la vida real: productor/consumidor.


productor consumidor
while(true) while(true)
tabla
{ 0 {
producir_elemento(); 1 if (contador==0)
ins ext sleep();
if (contador==N) 2
sleep(); 3 retirar_elemento();
almacenar_elemento(); contador--;
contador++; N-1 if (contador==(N-1))
contador=N
contador=2
contador=1
contador=3
contador=0 wakeup(productor);
if (contador==1)
wakeup(consumidor); usar_elemento();
} }

6
1. Suspensión y reanudación
Tema 7: Concurrencia y Sincronización

 Problemas:
Suspensión es incondicional
• ¡No hay atomicidad comprobación-acción!
Procesos deben conocerse entre sí
Un único estado de espera por proceso
• Procesos están “o despiertos o dormidos”
• Si proceso está dormido, no hay vinculación alguna con la
causa por la que está en dicho estado

7
Índice:
Tema 7: Concurrencia y Sincronización

1. Suspensión y Reanudación

2. Semáforos

3. Propiedades y Características de los


Semáforos

4. Problemas Clásicos de Concurrencia


8
2. Semáforos
Tema 7: Concurrencia y Sincronización

1. Concepto de semáforo

2. Implementación de semáforos

3. Semáforos en la práctica

4. Semáforos binarios

9
2. Semáforos
Tema 7: Concurrencia y Sincronización

1. Concepto de semáforo

2. Implementación de semáforos

3. Semáforos en la práctica

4. Semáforos binarios

10
2.1 Concepto de semáforo
 E. W. Dijkstra (1.965)
Tema 7: Concurrencia y Sincronización

 Semaforo = tipo abstracto de datos, que encapsula:


Un contador entero
Una lista de procesos bloqueados en el semáforo
 Operaciones sobre semáforos:
down(s):
• si contador = 0, proceso se bloquea en semáforo
• decrementa contador
up(s):
• Incrementa contador
• Si había algún proceso bloqueado en semáforo, reanuda uno
 ¡Ambas operaciones son atómicas!
11
2.1 Concepto de semáforo
 Utilidad: proteger acceso a recursos compartidos
Tema 7: Concurrencia y Sincronización

A cada recurso compartido, se asocia semáforo con


valor inicial 1.
Secciones críticas asociadas al recurso:
• Protocolo de entrada: down(s)
• Protocolo de salida: up(s)

 Ventajas:
Robustez
• Comprobación/Acción son atómicas
Procesos que se coordinan no necesitan conocerse entre

• Sólo necesitan conocer semáforos que comparten
Flexibilidad
12
• Tanto semáforos como recursos compartidos
2. Semáforos
Tema 7: Concurrencia y Sincronización

1. Concepto de semáforo

2. Implementación de semáforos

3. Semáforos en la práctica

4. Semáforos binarios

13
2.2 Implementación de semáforos
Tema 7: Concurrencia y Sincronización

struct s_semaforo struct nodoproc


{ {
int contador; PID proceso;
listaproc bloqueados; struct nodoproc *sig;
} }
typedef s_semaforo *semaforo; typedef struct nodoproc *listaproc

void down(semaforo s)
{
if (s->contador>0)
s->contador--; void up(semaforo s)
{
else
if (lista_vacia(s->bloqueados))
{
s->contador++;
insertar_en_lista (&s->bloqueados, getpid());
else
sleep();
{
}
int pid=sacar_de_lista(s->bloqueados);
}
semaforo CrearSemaforo(int valor); wakeup(pid);
}
void DestruirSemaforo(semaforo s);
} 14
2. Semáforos
Tema 7: Concurrencia y Sincronización

1. Concepto de semáforo

2. Implementación de semáforos

3. Semáforos en la práctica

4. Semáforos binarios

15
2.3 Semáforos en la práctica
Productor/Consumidor con semáforos
Tema 7: Concurrencia y Sincronización

productor consumidor
while(true) tabla
while(true)
{ {
0
producir_elemento(); down(llenas);
1
ins ext down(excmut);
down(vacias);
down(excmut); 2
down(excmut);
down(vacias); retirar_elemento();
contador=0 3
almacenar_elemento(); up(excmut);
excmut=1 up(vacias);
up(excmut); N-1
up(llenas); consumir_elemento();
} vacias=N }
llenas=0

16
2. Semáforos
Tema 7: Concurrencia y Sincronización

1. Concepto de semáforo

2. Implementación de semáforos

3. Semáforos en la práctica

4. Semáforos binarios

17
2.4 Semáforos binarios
 Caso particular: semáforos con sólo dos estados:
Tema 7: Concurrencia y Sincronización

Abierto (true, 1, …)
Cerrado (false, 0, …)

 Operaciones sobre semáforos binarios:


down(s):
• si estado=cerrado, proceso se bloquea en semáforo
• estado=cerrado
up(s):
• estado=abierto
• Si había algún proceso bloqueado en semáforo, reanuda uno

 ¿Son más potentes semáforos contadores que


semáforos binarios? 18
2.4 Semáforos binarios
Tema 7: Concurrencia y Sincronización

struct s_semaforo
{
void down(semaforo s)
int contador;
{
semaforo_b blqd; /* =abierto */
down_b(s->blqd);
semaforo_b exc; /* =abierto */
semaforo_b esp; /* =cerrado*/ down_b(s->exc);
} --(s->contador);
if (s->contador >=0)
typedef s_semaforo *semaforo;
up_b(s->exc);
else
void up(semaforo s)
{
{
up_b(s->exc);
down_b(s->exc);
down_b(s->esp);
++(s->contador); }
if (s->contador <=0)
up_b(s->blqd);
up_b(s->esp);
}
up_b(s->exc);
}

19
Índice:
Tema 7: Concurrencia y Sincronización

1. Suspensión y Reanudación

2. Semáforos

3. Propiedades y Características de los


Semáforos

4. Problemas Clásicos de Concurrencia


20
3. Propiedades y Características de los Sem.
 Reglas generales:
Tema 7: Concurrencia y Sincronización

Si un semáforo controla sección crítica,


• Cerrar lo más tarde posible
• Abrir tan pronto como sea posible
Secciones críticas anidadas:
• Evitar en la medida de lo posible
• down(a) y despues down(b)→ admisible si proceso que hace
up(b) no hace down(a)

 Selección proceso que se desbloquea up:


No especificado
Depende de implementación:
• FIFO, aleatorio, prioridad…
Los programas nunca deben depender de este detalle!
21
3. Propiedades y Características de los Sem.
 Granularidad: nº de recursos controlados por cada
Tema 7: Concurrencia y Sincronización

semáforo
Granularidad fina: un recurso por semáforo
Granularidad gruesa: un semáforo para todos los
recursos:

22
3. Propiedades y Características de los Sem.
Granularidad fina: Granularidad gruesa:
Tema 7: Concurrencia y Sincronización

 Ventajas:  (inversa)
mayor grado de
paralelismo
 Inconvenientes:
mayor número de semáforos
¡Posibilidad de interbloqueo!
P1

P2
23
Índice:
Tema 7: Concurrencia y Sincronización

1. Suspensión y Reanudación

2. Semáforos

3. Propiedades y Características de los


Semáforos

4. Problemas Clásicos de Concurrencia


24
4. Problemas Clásicos de Concurrencia
Los Filósofos Comensales
Tema 7: Concurrencia y Sincronización

void filosofo (int i)


{
while(true)
{
pensar();
coger_tenedor(derecho(i));
coger_tenedor(izquierdo(i));
comer();

soltar_tenedor(derecho(i));
soltar_tenedor(izquierdo(i));
}
}

25
4. Problemas Clásicos de Concurrencia
 ¿Una posible solución?
Tema 7: Concurrencia y Sincronización

void filosofo (int i)


{
while(true)
{
pensar();
down (s);
coger_tenedor(derecho(i));
coger_tenedor(izquierdo(i));
comer();
soltar_tenedor(derecho(i));
soltar_tenedor(izquierdo(i));
up (s)
}
}

26
4. Problemas Clásicos de Concurrencia
f[0] void coger_tenedores(int i)
Tema 7: Concurrencia y Sincronización

{
down(excmut);
f[N] estado[i]= HAMBRIENTO;
probar(i);
void soltar_tenedores(int i)
up(excmut);
{
down(f[i]);
down(excmut);
excmut }
estado[i]= PENSANDO;
f[1] probar(izquierdo(i));
f[3] probar(derecho(i));
up(excmut);
void filosofo (int i) }
{
void
f[2]probar (int i)
while(true)
{
{
if ((estado[i]==HAMBRIENTO) && (estado[izquierdo(i) != COMIENDO)
pensar();
&& (estado[derecho(i)] != COMIENDO)
coger_tenedores(i);
{
comer();
estado[i]= COMIENDO;
soltar_tenedores(i);
up(f[i])
}
}
} 27
}

También podría gustarte