2011-01-23 19 views
5

Sto acquisendo alcune risorse in ordine crescente. Quale versione è migliore? Mi è stato detto che il n. 2 porta alla fame di discussioni che richiedono risorse numerate più elevate. È vero? Se sì, come e perché?Acquisizione risorse e 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: Si scopre che ordine in cui si rilascia le risorse fa la differenza, non i costrutti di cui sopra. Se li rilasci nell'ordine in cui li hai ricevuti, succede la fame, se in senso opposto probabilmente no.

+0

Non dovrebbe esserci una chiamata 'acquire_resource (a [i]) 'da qualche parte? – caf

+0

Ho aggiunto l'acquisizione. – niteria

+0

http://stackoverflow.com/questions/1162587/what-is-starvation una definizione di fame – niteria

risposta

3

Entrambi stanno per essere praticamente equivalente, dal momento che nell'esempio 1 il filo sarà quasi sempre riacquisire il mutex senza dormire subito dopo lo sbloccaggio, poiché ci sono solo due espressioni valutate in mezzo.

+0

Puoi spiegare in qualche modo perché nessuno sarebbe morto di fame al secondo posto? – niteria

+0

@niteria: Provare un negativo è notoriamente difficile. Dipenderà da cosa fanno i thread oltre a questo ciclo - passano un tempo significativo * non * in possesso di una qualsiasi delle risorse? Posso dire, tuttavia, che i due cicli che hai dato sono equivalenti: sbloccare un mutex * non * implica cedere e i camerieri mutex non sono in coda. – caf

+0

Hai ragione, il problema era con l'ordine di liberare le risorse. Sai perché l'ordine opposto aiuta? – niteria

2

Provoca più fame quando le risorse sono sempre disponibili e pthread_cond_wait non ha bisogno di essere eseguito. In tal caso avresti il ​​mutex l'intero ciclo. Quindi, se N è molto grande, bloccando l'intero ciclo potresti morire di fame altri thread che hanno bisogno del mutex.

Generalmente è una buona idea bloccare il più piccolo capannone della regione per evitare la fame di altri thread e deadlock.

Considera anche quando qualcuno arriva per mantenere questo ciclo. Sarà molto facile aggiungere alcune istruzioni di istruzioni/funzioni nel corpo del ciclo for e creare più fame. Il manutentore potrebbe facilmente perdere il blocco nel codice. È meglio impedirlo creando una funzione incaricata di acquisire risorse i. Questa funzione sarebbe responsabile di tutto il blocco, eliminando ogni possibilità che il codice chiamante potesse estendere le dimensioni della sezione critica.

// 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

Ma pthread_cond_wait rilascia mutex o thread acquisisce con successo tutte le risorse e quindi rilascia il mutex. Non vedo come succede la fame. – niteria

+0

@niteria - La tua risposta è corretta, ho cambiato la risposta di conseguenza –

+0

Ma N è finito (nel mio caso inferiore a 100) e nel caso in cui tutte le risorse siano disponibili termina in un tempo finito, quindi il thread in attesa di mutex alla fine lo ottiene. Quindi la fame non succede. – niteria

0

Avrei il blocco e lo sblocco nella funzione resource_available, quindi bloccherò solo a destra prima dell'attesa - sblocco subito dopo.