2011-01-23 12 views
5

Estoy adquiriendo algunos recursos en orden creciente. ¿Qué versión es mejor? Me dijeron que # 2 conduce a la inanición de los hilos que desean recursos de mayor número. ¿Es esto cierto? Si es así, ¿cómo y por qué?Adquisición de recursos y pthreads

a[] sorted array 

1.

for(int i = 1; i < N; ++i) { 
    lock(mutex) 
    while(!resource_available[a[i]]) { 
    pthread_cond_wait(&cond_w[a[i]], &mutex); 
    } 
    resource_available[a[i]] = 0; 
    unlock(mutex) 
} 

2.

lock(mutex) 
for(int i = 1; i < N; ++i) { 
    while(!resource_available[a[i]]) { 
    pthread_cond_wait(&cond_w[a[i]], &mutex); 
    } 
    resource_available[a[i]] = 0; 
} 
unlock(mutex) 

EDIT: Resulta que el orden en el que se libera recursos que hace la diferencia, no construcciones anteriores. Si los libera para que los haya recibido, la inanición ocurre, si es opuesta, entonces probablemente no.

+0

¿No debería haber una llamada a 'acquire_resource (a [i])' allí? – caf

+0

Agregué adquisición. – niteria

+0

http://stackoverflow.com/questions/1162587/what-is-starvation una definición de inanición – niteria

Respuesta

3

Ambos van a ser prácticamente equivalente, ya que en el ejemplo 1 el hilo casi siempre volver a adquirir el mutex sin dormir inmediatamente después de desbloquear, ya que sólo hay dos expresiones evaluadas en el medio.

+0

¿Puedes explicar de alguna manera por qué nadie se muere de hambre en el n. ° 2? – niteria

+0

@niteria: Probar un negativo es notoriamente difícil. Dependerá de lo que hagan los hilos distintos de este ciclo: ¿gastan un tiempo significativo * no * en ninguno de los recursos? Puedo decir, sin embargo, que los dos bucles que ha dado son equivalentes: desbloquear un mutex no * implica * ceder, y los servidores de exclusión mutua no están en cola. – caf

+0

Tienes razón, el problema fue con el fin de liberar los recursos. ¿Sabes por qué el orden opuesto ayuda? – niteria

2

Causaría más inanición cuando los recursos están siempre disponibles y pthread_cond_wait no necesita ejecutarse. En ese caso, tendrías el mutex todo el ciclo. Entonces, si N es muy grande, bloqueando todo el ciclo podría estar muriendo de hambre a otros hilos que necesitan el mutex.

Generalmente es una buena idea bloquear la jerarquía de la región más pequeña para evitar la inanición de otros hilos y bloqueos.

Considere también cuando alguien viene para mantener este ciclo. Va a ser muy fácil englobar unas cuantas llamadas extra de declaraciones/funciones en el cuerpo del bucle for y crear más inanición. El mantenedor puede perder fácilmente el bloqueo en el código. Lo mejor es evitar esto creando una función a cargo de adquirir el recurso i. Esta función sería responsable de todos los bloqueos, eliminando cualquier posibilidad de que el código de llamada pueda extender el tamaño de la sección crítica.

// blocks till resource resourceNum is obtained 
void acquire_resource(int resourceNum) 
{ 
    lock(mutex) 
    while(!resource_available[a[i]]) { 
     pthread_cond_wait(&cond_w[a[i]], &mutex); 
    } 
    unlock(mutex) 
} 

for(int i = 1; i < N; ++i) { 
    acquire_resource(i); 
} 
+0

Pero ya sea pthread_cond_wait libera mutex o thread adquiere con éxito todos los recursos y luego libera mutex. No veo cómo pasa el hambre. – niteria

+0

@niteria - Está en lo correcto, cambié mi respuesta en consecuencia –

+0

Pero N es finito (en mi caso menos de 100) y en caso de que todos los recursos estén disponibles, termina en tiempo finito, por lo que el hilo esperando mutex finalmente lo obtiene. Entonces el hambre no sucede. – niteria

0

Me gustaría tener el bloqueo y desbloqueo en la función resource_available, y luego solo bloquear justo antes de esperar - desbloquear inmediatamente después.