interbloqueo cp
Post on 03-Mar-2016
17 Views
Preview:
DESCRIPTION
TRANSCRIPT
-
Introduccin a Concurrencia II.Interbloqueo y Condiciones
Juan Quintela. Javier Pars.{quintela, javier.paris}@udc.es
-
Interbloqueo (Deadlock)
int protected_add(int *v1, mutex *m1, int *v2, mutex *m2) {
int x;
lock(m1);
lock(m2);
x=v1+v2;
unlock(m2);
unlock(m1);
return x;
}
Interbloqueo es una situacin en que dos o ms procesos estn esperando por recursos que tiene ocupado el otro.
Ejemplo con una funcin que devuelve la suma de dos variables protegidas:
-
Interbloqueo
Desde dos threads distintos se llama a la funcin con las mismas variables pero en orden cambiado:
int valor1, valor2; // Dos variables compartidas
mutex m_valor1, m_valor2; // Mutex para proteger las variables valor1 y valor2 respectivamente
thread1:
protected_add(&valor1, &m_valor1, &valor2, &m_valor2); thread2:
protected_add(&valor2, &m_valor2, &valor1, &m_valor1);
-
InterbloqueoThread 1:
int protected_add(
int *v1 (=valor1),
mutex *m1(=m_valor1),
int *v2(=valor2),
mutex *m2 (=m_valor2))
{
int x;
lock(m1);
lock(m2);
x=v1+v2;
unlock(m2);
unlock(m1);
return x;
}
Thread 2:
int protected_add(
int *v1 (=valor2),
mutex *m1(=m_valor2),
int *v2(=valor1),
mutex *m2 (=m_valor1))
{
int x;
lock(m1);
lock(m2);
x=v1+v2;
unlock(m2);
unlock(m1);
return x;
}
-
Interbloqueo
Thread 1:
int protected_add(
int *v1 (=valor1),
mutex *m1(=m_valor1),
int *v2(=valor2),
mutex *m2 (=m_valor2))
{
int x;
lock(m_valor1);
lock(m_valor2);
x=valor1+valor2;
unlock(m_valor2);
unlock(m_valor1);
return x;
}
Thread 2:
int protected_add(
int *v1 (=valor2),
mutex *m1(=m_valor2),
int *v2(=valor1),
mutex *m2 (=m_valor1))
{
int x;
lock(m_valor2);
lock(m_valor1);
x=valor2+valor1;
unlock(m_valor1);
unlock(m_valor2);
return x;
}
Cambiamos los nombres de las variables en el cdigo para ver ms clara la ejecucin.
-
Interbloqueo
Thread 1:
int protected_add(
int *v1 (=valor1),
mutex *m1(=m_valor1),
int *v2(=valor2),
mutex *m2 (=m_valor2))
{
int x;
lock(m_valor1);
lock(m_valor2);
x=valor1+valor2;
unlock(m_valor2);
unlock(m_valor1);
return x;
}
Thread 2:
int protected_add(
int *v1 (=valor2),
mutex *m1(=m_valor2),
int *v2(=valor1),
mutex *m2 (=m_valor1))
{
int x;
lock(m_valor2);
lock(m_valor1);
x=valor2+valor1;
unlock(m_valor1);
unlock(m_valor2);
return x;
}
El thread 1 bloquea m_valor1, y el thread 2 bloquea m_valor2
-
Interbloqueo
Thread 1:
int protected_add(
int *v1 (=valor1),
mutex *m1(=m_valor1),
int *v2(=valor2),
mutex *m2 (=m_valor2))
{
int x;
lock(m_valor1);
lock(m_valor2); // Espera eterna
x=valor1+valor2;
unlock(m_valor2);
unlock(m_valor1);
return x;
}
Thread 2:
int protected_add(
int *v1 (=valor2),
mutex *m1(=m_valor2),
int *v2(=valor1),
mutex *m2 (=m_valor1))
{
int x;
lock(m_valor2);
lock(m_valor1); // Espera eterna
x=valor2+valor1;
unlock(m_valor1);
unlock(m_valor2);
return x;
}
El thread 2 intenta bloquear m_valor2, pero est bloqueado por el thread 2, y el thread 2 intenta bloquear m_valor1, pero est bloqueado por el thread 1.=> El thread 1 y el thread 2 estn en interbloqueo, porque cada uno espera por el otro.
-
Interbloqueo
Condiciones necesarias para que exista: Exclusin mutua: existen recursos no compartibles. Hold and wait: se permite que un proceso tenga
recursos reservados mientras espera para reservar otros.
No apropiacin: El sistema operativo no puede liberar recursos reservados.
Espera circular: Los procesos esperan por recursos reservados por procesos que esperan por los primeros.
Negar cualquiera de estas condiciones lo evita.
-
Interbloqueo: Tratamiento.
El interbloqueo se puede tratar mediante varias tcnicas, algunas aplicadas por el sistema operativo, otras por el propio sistema concurrente.
Algunos sistemas operativos (como Unix o Windows) ignoran el problema. Es tarea del programador de espacio de usuario evitar que se produzca.
-
Interbloqueo: Deteccin
En deteccin se permite que ocurran interbloqueos, y se corrigen despus.
Como el sistema operativo conoce que recursos tiene reservados un proceso, y por que recursos espera puede saber cuando se produce interbloqueo.
Una vez detectado puede Matar a los procesos involucrados. Apropiar recursos reservados y drselos a otro
proceso para resolver la situacin.
-
Interbloqueo: Prevencin
En prevencin se trata de evitar que una de las 4 condiciones necesarias se produzca: Exclusin mutua, impidiendo que los procesos tengan acceso
exclusivo a los recursos. Evitar hold and wait:
Haciendo que los procesos reserven todos los recursos necesarios de una vez en vez de mantener reservados unos mientras esperan.
Haciendo que los procesos liberen los recursos reservados si no pueden reservar ms.
Evitar la no apropiacin. Es necesario implementar algn mecanismo de roll-back.
La espera circular se puede evitar con una reserva ordenada de recursos.
-
Interbloqueo: Prevencin evitando hold and wait
Ejemplo: evitar mantener recursos reservados.int protected_add(int *v1, mutex *m1, int *v2, mutex *m2) {
int x;
int success=0;
do {
lock(m1);if(try_lock(m2)) { // Si no reserva m2 libera m1 y vuelve a probar
x=v1+v2;unlock(m2);success=1;
}unlock(m1);
} while(!success);
return x;
}
-
Interbloqueo: Prevencin con Reserva Ordenada
Ejemplo reserva ordenada:int protected_add(int *v1, mutex *m1, int ordenv1, int *v2, int ordenv2, mutex *m2)
{
int x;
if(ordenv1 < ordenv2) {
lock(m1); lock(m2);} else {
lock(m2); lock(m1);}
x=v1+v2;
unlock(m2);
unlock(m1);
}
-
Introduccin: Prevencin con Reserva Ordenada
Para llamarlo definimos un orden en los recursos:#define ORDENV1 1
#define ORDENV2 2
int valor1, valor2; // Dos variables compartidas
mutex m_valor1, m_valor2; // Mutex para proteger valor1 y valor2 thread1:
protected_add(&valor1, &m_valor1, ORDENV1,
&valor2, &m_valor2, ORDENV2); thread2:
protected_add(&valor2, &m_valor2, ORDENV2,
&valor1, &m_valor1, ORDENV1);
-
Interbloqueo: Evitacin
En evitacin se intenta prevenir que el sistema entre en una situacin de interbloqueo conociendo el estado del sistema y los recursos que los procesos pueden reservar en el futuro.
Requiere conocer a priori el uso de recursos que va a hacer un proceso, lo que limita mucho su uso.
-
Inanicin
Un proceso puede estar esperando acceso a un recurso compartido sin conseguirlo. Esta situacin se denomina inanicin.
Por ejemplo, si requerimos la reserva de todos los recursos simultneamente, los procesos que requieran una gran cantidad de recursos pueden quedar en este estado si hay muchos procesos que requieren pocos compitiendo por ellos.
-
InanicinEjemplo: Un thread que necesita bloquear muchos recursos.
mutex *m1, *m2, *m3;
void *bloqueo_mucho(void *arg) {while(1) {
lock(m1);if (try_lock(m2)) {
if(try_lock(m3)) {// Hacer algo con los recursos protegidos por m1, m2 y m3
}
unlock(m2);}unlock(m1);
}
}
Se usa trylock porque si no se consigue bloquear m2 o m3 queremos
minimizar el tiempo que se mantienen mutex bloqueados => implica que el
thread se tiene que encontrar los 3 mutex libres para tener xito.
-
InanicinOtros threads solo necesitan un mutex:
void *bloqueam1(void *arg) {lock(m1);
// Hacer algo con el recurso protegido por m1
unlock(m1);
}
void *bloqueam2(void *arg) {lock(m2);
// Hacer algo con el recurso protegido por m2
unlock(m2);
}
void bloqueam3(void *arg) {lock(m3);
// Hacer algo con el recurso protegido por m3
unlock(m3);
}
-
Inanicin
Que ocurre si hay muchos threads ejecutando bloquem1, bloqueam2 y bloqueam3? => Es muy probable que en todo momento alguno de los mutex est bloqueado.
El thread que ejecuta bloqueamucho no es capaz de entrar en su seccin crtica => inanicin.
-
Sincronizacin por Condiciones
Una condicin permite a los procesos/threads suspender su ejecucin hasta que se les despierte.
Se disearon porque a veces es necesario interrumpir la ejecucin en medio de una seccin crtica hasta que el estado de un recurso compartido cambie por la accin de otro proceso.
Ese otro proceso es el que debe encargarse de despertar a los que puedan estar esperando.
-
Sincronizacin por Condiciones
En la librera pthread:
pthread_cond_t
int pthread_cond_init(pthread_cond_t *, pthread_condattr_t *);
int pthread_cond_signal(pthread_cond_t *);
int pthread_cond_broadcast(pthread_cond_t *);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int pthread_cond_timedwait(pthread_cond_t *,
pthread_mutex_t *, const struct timespec *);
-
Sincronizacin por Condiciones
Ejemplo: Threads que comparten una cach en memoria guardada en un array indexado por un hash. Las posiciones se reservan hasta que se liberen explcitamente.
dato cache[CACHE_SIZE];
int reservado[CACHE_SIZE];
pthread_mutex_t m;
pthread_cond_t espera[CACHE_SIZE];
-
Sincronizacin por Condiciones
void insert(dato d) {int pos = hash(d);
pthread_mutex_lock(&m);
while(reservado[pos])pthread_cond_wait(&espera[pos],&m);
reservado[pos]=1;
cache[pos]=d;
pthread_mutex_unlock(&m);
}
-
Sincronizacin por condiciones
void liberar(dato d) {int pos = hash(d);
pthread_mutex_lock(&m);
reservado[pos]=0;
pthread_cond_signal(&reservado[pos]);
pthread_mutex_unlock(&m);
}
-
Sincronizacin por Condiciones
Internamente el wait hace de forma atmica:
wait(cond *c, mutex *m) {unlock(m);
espera(m);
lock(m);
}
Atmico
-
Sincronizacin por Condiciones
Por que es necesario bloquear el mutex para esperar y cuando se manda la seal? => Antes de esperar siempre se comprueba una condicin, y es necesario que la comprobacin no cambie hasta que el thread est esperando.
-
Sincronizacin por Condiciones
void insert(dato d) {int pos = hash(d);
while(reservado[pos])pthread_cond_wait(
&espera[pos]);
pthread_mutex_lock(&m);
reservado[pos]=1;
cache[pos]=d;
pthread_mutex_unlock(&m);
}
void liberar(dato d) {
int pos = hash(d);
pthread_cond_signal(&reservado[pos]);
pthread_mutex_lock(&m);
reservado[pos]=0;
pthread_mutex_unlock(&m);
}
Como ejemplo, en el caso anterior, quitando los bloqueos antes de comprobar:
-
Sincronizacin por Condiciones
void insert(dato d) {int pos = hash(d);
while(reservado[pos])pthread_cond_wait(
&espera[pos]);
pthread_mutex_lock(&m);
reservado[pos]=1;
cache[pos]=d;
pthread_mutex_unlock(&m);
}
void liberar(dato d) {
int pos = hash(d);
pthread_cond_signal(&reservado[pos]);
pthread_mutex_lock(&m);
reservado[pos]=0;
pthread_mutex_unlock(&m);
}
El primer thread comprueba la condicin, mientras el segundo calcula el hash.
-
Sincronizacin por Condiciones
void insert(dato d) {int pos = hash(d);
while(reservado[pos])pthread_cond_wait(
&espera[pos]);
pthread_mutex_lock(&m);
reservado[pos]=1;
cache[pos]=d;
pthread_mutex_unlock(&m);
}
void liberar(dato d) {
int pos = hash(d);
pthread_cond_signal(&reservado[pos]);
pthread_mutex_lock(&m);
reservado[pos]=0;
pthread_mutex_unlock(&m);
}
El primer thread hace la comprobacin, como el recurso est ocupado la condicin secumple y entra por el if. El segundo manda la seal, como nadie espera no pasa nada.
-
Sincronizacin por Condiciones
void insert(dato d) {int pos = hash(d);
while(reservado[pos])pthread_cond_wait(
&espera[pos]);
pthread_mutex_lock(&m);
reservado[pos]=1;
cache[pos]=d;
pthread_mutex_unlock(&m);
}
void liberar(dato d) {
int pos = hash(d);
pthread_cond_signal(&reservado[pos]);
pthread_mutex_lock(&m);
reservado[pos]=0;
pthread_mutex_unlock(&m);
}
El primer thread espera, pero como la seal ya se envi se queda esperandoindefinidamente. La seal se ha perdido (Lost Wakeup).
top related