私はTPLと遊んでいて、同じ辞書に並行して読み書きすることでどれくらいの混乱を招くかを調べようとしていました。.Netで辞書を読み書きするときにデッドロックが発生する可能性はありますか?
だから私はこのコードを持っていた:それはかなり確かに台無しにされた
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));
}
}
を、スローされた例外の多くは、キーが配列の境界の外に、インデックスに関するいくつか存在しませんほとんどについて、ありました。
しかし、しばらくの間、アプリケーションを実行した後、CPUのパーセンテージは25%にとどまり、マシンには8つのコアがあります。 だから私はそれが2つのスレッドは、フル容量で実行されていると仮定します。
その後、私はそれにドットトレースを実行し、そしてこの得た:それは2つのスレッドが100%で実行されている、私の推測と一致する
を。
どちらもDictionaryのFindEntryメソッドを実行しています。
は、その後、私は再びアプリを走った、ドットトレースで、今回は結果が若干異なります。
この時、1つのスレッドFindEntry、他の挿入が実行されています。
私の最初の直感は、それがデッドロックされていたということでしたが、それができないと思っていました。共有リソースは1つしかなく、ロックされていません。
これはどのように説明する必要がありますか?
ps:問題を解決するつもりはありません。ConcurrentDictionaryを使用して修正することも、並列集計を行うこともできます。私はちょうどこれについて合理的な説明を探しています。
Findentryは、エントリを見つけることを推測できます。後で変更されるいくつかのローカル変数を保持するため、ループ終了条件は決して終了しません。これは、別のスレッドによって変更された項目数が変更されないと仮定しているためです。 –
デッドロックではありませんが、内部状態が乱れて無限ループが発生しますか? – CuiPengFei
はい....... – pm100