2011-01-12 13 views
10

Capisco che una delle cause principali per l'indice al di fuori dell'errore di limiti per un oggetto Dizionario è collisione di thread. (Leggendo e scrivendo allo stesso dizionario allo stesso tempo) Tuttavia, mi sono imbattuto in un caso di perplessità in cui la collisione tra thread non è una spiegazione sufficiente.Le cause alternative per Index erano al di fuori dei limiti dell'array nel dizionario .Net

Ecco la situazione: Ho scritto codice che implementa il dizionario in un modo non sicuro per l'elaborazione multi-thread.

Il codice è stato implementato come servizio Web su due server, Server A e Server B. È possibile accedere ai server tramite un servizio di bilanciamento del carico che invierà le richieste ai server A e B in modalità round robin.

Ora ecco la parte difficile. L'errore viene visualizzato SOLO sul server A e mai sul server B. Secondo il nostro team hardware, entrambi i server sono identici. Sebbene la collisione tra thread sia intrinsecamente un processo casuale, dovrebbe comunque influenzare allo stesso modo entrambi i miei server. Vedo più di 50 istanze dell'errore su un server e 0 su un altro. È statisticamente improbabile che le collisioni tra thread avvengano solo su uno dei miei server mentre l'altra è in esecuzione senza errori.

Sto già modificando l'applicazione per renderlo thread più sicuro, ma quali altri motivi possono esistere per questo errore da generare durante l'operazione di inserimento di un oggetto Dictionary?

+0

Sei sicuro che il bilanciamento del carico invia richieste al Server B? Forse riguarda solo il primo server. –

+0

Forse un server ha un sistema operativo a 32 bit e l'altro a 64 bit? –

+0

@ petro.sidlovskyy Ho confermato che entrambi i server hanno traffico basato su file di registro – Joshua

risposta

7

Sebbene filo di collisione è di per sé un processo casuale

Niente affatto. Dipende in modo critico dal tempo. E i tempi possono essere ripetibili, i sistemi tendono a stabilirsi in modelli specifici.Uno strumento diagnostico di thread race come il CHESS di Microsoft Research funziona iniettando ritardi casuali nell'esecuzione di un thread. Per far cadere il sistema da un tale schema. Come ogni tanto fa da solo, ma solo una volta alla settimana. Il numero è casuale, ma non abbastanza casuale da darti una possibilità di eseguire il debug del problema.

Quindi, vedere un server fallire e non l'altro non significa nulla. Il bilanciamento del carico probabilmente ha qualcosa a che fare con questo. Non sarai mai in grado di capire il motivo esatto perché non puoi scoprire cosa è successo 50 volte. Non è abbastanza

1

Questo è probabilmente inverosimile, ma ti capita di sapere se le tue connessioni ai due server attraverso il bilanciamento del carico sono uguali? (Non so davvero nulla su come funziona il bilanciamento del carico, quindi questo potrebbe essere un pensiero stupido fin dall'inizio.)

Sto solo pensando, diciamo che hai un po 'più di latenza di rete nella tua connessione al Server B rispetto al Server A. Ciò potrebbe fornire una distanza sufficiente tra le richieste dei client su quel server con conseguente accesso al dizionario, permettendoti di farla franca con il tuo codice multithread che non stia parlando in modo sicuro.

Se le richieste raggiungono il server A un po 'più veloce, ciò potrebbe fare la differenza e fornire gli errori fuori intervallo.

Come ho detto, probabilmente inverosimile, solo un'idea. Ho pensato che non poteva far male buttarlo lì fuori.

0

Non riesco a spiegare perché non funziona su un server ma non sull'altro. I tuoi problemi sono comunque problemi di multithreading.

Come avrete notato, questo non funzionerà quando in un ambiente multithread:

if (!dict.ContainsKey("myKey")) 
    dict.Add("myKey", value); 

Lo stesso vale per:

if (dict.ContainsKey("myKey")) 
    return dict["myKey"]; 

Cosa potrebbe sorprenderà è che TryGetValue non è thread-safe o:

MyObject obj; 
return dict.TryGetValue("myKey", out obj) ? obj : null; 

Riferimento: http://www.grumpydev.com/2010/02/25/thread-safe-dictionarytkeytvalue/

0.123.
+0

Non dovrebbe sorprendervi visto che non sono raccolte thread-safe nel primo caso? – Kurru

Problemi correlati