2010-07-05 2 views
6

Mi chiedevo se qualcuno è a conoscenza di una buona panoramica delle tecniche di debug per le applicazioni multithread. Idealmente, sto cercando un'analisi basata sui casi: deadlock, starvation, stato condiviso corrotto, ...Tecniche di debug multithread

. Netto specifico o generico.

+6

Ci sono molti strumenti interessanti, ma non trascurare il semplice approccio della semplice lettura del codice. Ho fatto il debugging multithreading per anni, ed è uno dei metodi più efficaci. –

+0

Vero. Funziona piuttosto bene. Sto osservando più tecniche ("come" questo) di strumenti. – Mau

+0

+1 @Stephen Veramente vero. –

risposta

11

Non sono a conoscenza di un articolo o di un libro che risolva quello che stai cercando, quindi ecco le mie "lezioni apprese" da 12 anni di debug multithreading su Windows (entrambi non gestiti e gestiti).

Come ho affermato nel mio commento, la maggior parte del mio "debug multithreading" viene effettivamente eseguita tramite una revisione manuale del codice, alla ricerca di questi problemi.

deadlock e corrotto Shared Stato

documento lock hierarchies (sia l'ordine e che stato proteggono in comune), e assicurano che siano coerenti. Questo risolve la maggior parte dei problemi di deadlock e problemi di stato condiviso corrotti.

(Nota: il collegamento sopra per "gerarchie di blocco" si riferisce a un articolo del Dr. Dobbs di Herb Sutter, che ha scritto un'intera serie di articoli Effective Concurrency che consiglio vivamente).

Altro su deadlock

Utilizzare RAII for all synchronization. Ciò garantisce che i blocchi vengano rilasciati in caso di eccezioni. Preferisci la frase "lock" per provare/finalmente.

(Si noti che RAII in .NET dipende da IDisposable, non Finalize e presuppone che il codice client utilizzi correttamente un blocco using).

fame

Rimuovere eventuali modifiche di priorità di thread. La corretta definizione delle priorità è in realtà un po 'contro-intuitiva: è meglio dare al thread più lavoro per fare una priorità più bassa, e dare priorità maggiori ai thread che sono vincolati all'I/O (incluso il thread dell'interfaccia utente).Dal momento che Windows lo fa automaticamente (vedi Windows Internals), non c'è davvero alcun motivo per cui il codice sia coinvolto.

In generale

Rimuovere tutto il codice senza blocchi che è stato scritto in-house. Quasi certamente contiene bug sottili. Sostituirlo con .NET 4 lock-free collections e synchronization objects o modificare il codice in base al blocco.

Utilizzare concetti di livello superiore per la sincronizzazione. Il Task Parallel Library e unified cancellation in .NET 4 Rimuovere praticamente qualsiasi esigenza per l'utilizzo diretto di ManualResetEvent, Monitor, Semaphore, ecc

concetti Usa più alto livello per la parallelizzazione. Lo TPL and PLINQ in .NET 4 dispone di algoritmi di autobilanciamento integrati completi di partizioni intelligenti e code di work-stealing per fornire automaticamente una parallelizzazione ottimale. Per i rari casi in cui la parallelizzazione automatica non è ottimale, sia TPL che PLINQ espongono un numero enorme di manopole modificabili (schemi di partizionamento personalizzati, flag di funzionamento di lunga durata, ecc.).

C'è un'altra tecnica che ho trovato utile per qualsiasi classe che ha i suoi metodi chiamati da diversi thread: documenta quali metodi eseguire su quali thread. Di solito, questo viene aggiunto come commento all'inizio del metodo. Assicurati che ogni metodo venga eseguito solo in un contesto di thread noto (ad es. "Su un thread UI" o "su un thread ThreadPool" o "sul thread in background dedicato"). Nessuno dei metodi dovrebbe dire "su qualsiasi thread" a meno che tu non stia scrivendo una classe di sincronizzazione (e se stai scrivendo una classe di sincronizzazione, chiediti se davvero dovresti farlo).

Infine, assegna un nome alle discussioni. Questo aiuta a distinguerli facilmente quando si usa il debugger VS. .NET supporta questo tramite la proprietà .

6

Non è quello che stai chiedendo ma forse trovi interessante CHESS.

+0

Interessante, grazie. – Mau

+0

+1 per ... meraviglia. non avevo idea che esistesse una cosa del genere! viva CHESS! –

+0

È davvero fantastico. –

0

Ho usato Helgrind un subtool di Valgrind. Helgrind è un rilevatore di errori di thread e l'ho usato una o due volte per rilevare le condizioni di gara in alcuni dei miei codici. Può rilevare le seguenti cose.

  1. Utilizzo errato dell'API pthreads POSIX.
  2. Potenziali deadlock derivanti da problemi di ordine dei blocchi.
  3. Dati razziali - accesso alla memoria senza un adeguato blocco o sincronizzazione.

http://valgrind.org/docs/manual/hg-manual.html

Ovviamente unico strumento Linux per programmi di sistema, C/C++. Nessun Java o .NET.

0

Non credo che nessuna tecnica possa rilevare in modo affidabile tutti i problemi di multithreading, perché il codice che li causa è troppo complicato da analizzare. Nessuno strumento è in grado di rilevare tali problemi nemmeno in tempo reale, poiché lo strumento stesso necessita anche del tempo di esecuzione. Il programma di debug si comporterebbe in modo completamente diverso con lo strumento e senza.

Ho dovuto eseguire il debug di problemi in tempo reale che si sono verificati nella produzione solo una volta al mese! L'unica soluzione che ho trovato è di aggiungere il codice che rileva il problema e di scrivere le informazioni di traccia tramite i thread coinvolti. Ovviamente, la traccia deve essere ESTREMAMENTE veloce e non bloccante. strumenti usuali come Visual Studio sono troppo lento per tempo reale tracciamento, ma per fortuna, è facile scrivere il proprio traccia di memoria:

const int maxMessages = 0x100; 
const int indexMask = maxMessages-1; 
string[] messages = new string[maxMessages]; 
int messagesIndex = -1; 

public void Trace(string message) { 
    int thisIndex = Interlocked.Increment(ref messagesIndex) & indexMask; 
    messages[thisIndex] = message; 
} 

Una descrizione più dettagliata di questo approccio, che raccoglie anche le informazioni e le uscite di filo e la tempistica la traccia è piacevolmente a: CodeProject: Debug di codice multithreaded in tempo reale 1