Penso che l'intervista ti stia facendo una domanda trabocchetto. Se potessi usare l'analisi statica per evitare un deadlock ... nessuno avrebbe un deadlock!
Personalmente, quando cerco lo stallo, comincio a trovare funzioni in cui la sezione critica si estende oltre la chiamata di funzione. Per esempio
void func(){
lock(_lock){
func2();
}
}
Non è molto chiaro quello che sta facendo func2
. Forse invia un evento sullo stesso thread, il che significherebbe che l'evento fa ancora parte della sezione critica. Forse si blocca quindi su un blocco diverso. Forse si invia al threadpool e non è più rientrante perché è ora su un thread diverso! Questi tipi di luoghi sono dove puoi iniziare a vedere gli scenari di stallo: quando hai più posizioni di blocco non rientranti.
Altre volte, quando si tracciano scenari di deadlock, faccio il backtrack e cerco di trovare dove sono stati creati tutti i thread. Dò pensiero a ciascuna funzione e dove può effettivamente essere in esecuzione. Se non si è sicuri, può anche essere utile aggiungere la registrazione per registrare da dove proviene la chiamata alla funzione.
È inoltre possibile evitare i deadlock utilizzando strutture di dati senza blocchi (ma richiedono comunque altrettanti usi). Si desidera ridurre al minimo l'accesso alla struttura senza blocco perché ogni volta che si accede a esso può cambiare.
Come menzionato in un'altra risposta, è possibile utilizzare i mutex con timeout, ma non è garantito che funzionino sempre (cosa succede se il codice deve funzionare più a lungo del timeout?). È stato menzionato in un altro commento che questo è forse ciò che l'intervistatore stava chiedendo. Trovo che nella produzione questa non sia davvero una buona idea. I timeout variano in continuazione, forse c'è voluto più tempo del previsto per correre e colpire un timeout. Penso sia meglio lasciarlo a un punto morto, prendere una discarica di processo, quindi trovare esattamente cosa tenesse i lucchetti e risolvere il problema. Naturalmente, se i tuoi requisiti aziendali non lo consentono, puoi utilizzarlo come parte di una strategia di codifica difensiva insieme a scelte di posizionamento intelligenti.
Non sono d'accordo con la tua intervista che blocca sempre aggiungere un enorme problema di prestazioni. Serrature/mutex/ecc. Non contestati prima prova come spinlock prima di passare al sistema operativo e gli spinlock sono economici.
In generale, il modo migliore per evitare un deadlock è capire il flusso del programma. Ogni volta che introduci un nuovo oggetto di blocco, pensa a dove è usato e a cosa lo usa lungo la catena.
Si dovrà analizzare i modelli di bloccaggio ... Non riesco a pensare a una risposta molto compatto. –
Stava chiedendo un modo generico per verificare un deadlock? Tutto quello che so è guardando il codice e usando un po 'di intelligenza ... – TheKingDave
Per prevenire i deadlock, devi usare un'implementazione lockfree. Se è assolutamente necessario mantenere i blocchi, è necessario assicurarsi che quando sono richiesti più blocchi, gli oggetti bloccati siano bloccati in un ordine ben definito. – Nolonar