Ich spielte mit TPL und versuchte herauszufinden, wie groß das Durcheinander ist, wenn ich parallel zum selben Wörterbuch lese und schreibe.Ist es möglich, dass ein Wörterbuch in .Net eine Deadlock-Funktion auslöst, wenn es parallel gelesen und geschrieben wird?
So hatte ich diesen Code:
private static void HowCouldARegularDicionaryDeadLock()
{
for (var i = 0; i < 20000; i++)
{
TryToReproduceProblem();
}
}
private static void TryToReproduceProblem()
{
try
{
var dictionary = new Dictionary<int, int>();
Enumerable.Range(0, 1000000)
.ToList()
.AsParallel()
.ForAll(n =>
{
if (!dictionary.ContainsKey(n))
{
dictionary[n] = n; //write
}
var readValue = dictionary[n]; //read
});
}
catch (AggregateException e)
{
e.Flatten()
.InnerExceptions.ToList()
.ForEach(i => Console.WriteLine(i.Message));
}
}
Es war ziemlich in der Tat vermasselt, viele Ausnahmen geworfen waren, vor allem über Schlüssel nicht existiert, um nur einige zu Index des Arrays aus gebunden ist.
Aber nach dem Ausführen der App für eine Weile hängt es, und der CPU-Prozentsatz bleibt bei 25%, die Maschine hat 8 Kerne. Also ich nehme an, dass 2 Threads bei voller Kapazität laufen.
Dann lief ich DotTrace darauf und bekam dies:
Es ist meine Vermutung passt, zwei Threads bei 100%.
Beide die FindEntry-Methode von Dictionary ausführen.
Dann lief ich die App wieder, mit DotTrace, diesmal das Ergebnis ist etwas anders:
Diesmal ein Thread FindEntry, das andere Insert läuft.
Meine erste Intuition war, dass es totgesperrt ist, aber dann dachte ich, es könnte nicht sein, es gibt nur eine gemeinsame Ressource, und es ist nicht gesperrt.
Also wie soll das erklärt werden?
ps: Ich suche nicht, um das Problem zu lösen, könnte es behoben werden, indem Sie ein ConcurrentDictionary verwenden, oder indem Sie parallele Aggregation durchführen. Ich suche nur eine vernünftige Erklärung dafür.
Wie Sie erraten können, versucht Findetry einen Eintrag zu finden. Es behält einige lokale Variablen bei, die sich später ändern, was dazu führt, dass die Schleifenende-Bedingung niemals beendet wird, da angenommen wird, dass die Anzahl der Einträge, die von einem anderen Thread geändert wurde, sich nicht ändert. –
Es ist also keine tote Sperre, sondern eine Endlosschleife, die durch einen vermischten internen Zustand verursacht wird? – CuiPengFei
ja ........... – pm100