私はConcurrentQueue
という概念を中心に非常に基本的な質問がありました。キューはFIFOです。複数のスレッドがアクセスを開始すると、どのようにFIFOを保証するのですか? と仮定して、私はApple
,Oranges
,Lemon
,Peach
およびApricot
の順に追加しました。最初のTryTake
はApple
を返す必要があります。しかし、複数のスレッドが独自のTryTake
要求を出し始めるとどうなりますか?他のスレッドがApple
を返す前に、あるスレッドがLemon
を返す可能性がありますか?キューが空になるまで他のアイテムも返されると仮定しています。しかし、これらのリターンはFIFOの基本原則を支配するでしょうか?ConcurrentQueue .Net:マルチスレッドコンシューマ
答えて
ConcurrentQueue
自体の動作は、常にFIFOになります。我々はConcurrentQueue
から項目を「返す」のスレッドについて話すとき
、我々はあなたがデキューされたものを観察することができます操作のいくつかの並べ替えを行ってデキュー項目との両方を必要とする操作の話をしています。アウトプットを出力している場合でも、そのアイテムを別のリストに追加している場合でも、検査するまでキューから取り出したアイテムは実際には分かりません。
キュー自体はFIFOですが、デキューされたアイテムを検査するなどの他のイベントが発生する順序を予測することはできません。アイテムはデキューされたFIFOになりますが、その順序でキューから出て来るものを観察することもできないこともあります。異なるスレッドは、キューから項目を削除したのとまったく同じ順序で検査または出力を実行しないことがあります。
つまり、FIFOで発生することになりますが、必ずしもそうでない場合もあります。処理されたアイテムの正確なシーケンスが重要である場合は、ConcurrentQueue
から同時に読み取ることは望ましくありません。
これをテストしようとすると(私は何かを書こうとしています)、ほとんどの場合正確なFIFOシーケンスで処理されるアイテムが見つかるでしょう。
ここにコンソールアプリがあります。
- には、シングルスレッドの
ConcurrentQueue
に1~5000の数字を挿入します。 - これらのアイテムのそれぞれをデキューして別の
ConcurrentQueue
に移動するために並行操作を実行します。 これは「マルチスレッド消費者」です。 - 2番目のキュー内の項目を読み込み(シングルスレッド、もう一度)、順不同の番号を報告します。
何度も私はそれを実行し、何も順不同です。しかし、約50%の時間で、順不同の数が報告されます。したがって、元のシーケンスで処理されるすべての数値に基づいている場合、ほとんどの場合、ほぼすべての数値が発生します。しかし、そうではありません。正確なシーケンスは気にせず、バグがあり、予測できない場合はうまくいきます。
結論は、マルチスレッド処理の正確なシーケンスには依存しません。
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
namespace ConcurrentQueueExperiment
{
class Program
{
static void Main(string[] args)
{
var inputQueue = new ConcurrentQueue<int>();
var outputQueue = new ConcurrentQueue<int>();
Enumerable.Range(1,5000).ToList().ForEach(inputQueue.Enqueue);
while (inputQueue.Any())
{
Task.Factory.StartNew(() =>
{
int dequeued;
if (inputQueue.TryDequeue(out dequeued))
{
outputQueue.Enqueue(dequeued);
}
});
}
int output = 0;
var previous = 0;
while (outputQueue.TryDequeue(out output))
{
if(output!=previous+1)
Console.WriteLine("Out of sequence: {0}, {1}", previous, output);
previous = output;
}
Console.WriteLine("Done!");
Console.ReadLine();
}
}
}
- 1. .NETのConcurrentQueueとBlockingCollectionの違いは何ですか?
- 2. ConcurrentQueueのエンキューとTryDequeue
- 3. マルチスレッドコンシューマ、プロデューサCコード、実行していない?
- 4. kafka 0.9.0でマルチスレッドコンシューマを使用するには?
- 5. ConcurrentQueueのメソッドで再キューが必要です。>
- 6. C#ConcurrentQueueを条件でクリーニングする方法
- 7. ConcurrentQueueを使用してスレッドを処理する方法<T>
- 8. タイムアウトのある.NETの同時収集ですか?
- 9. .NET用の.NETエンティティフレームワーク
- 10. .NET 3.5対.NET 3.0
- 11. .NET用.NETライブラリのデプロイ
- 12. Migrate Application .Net 1.1 to .Net 4.0
- 13. /.NET
- 14. .NET
- 15. .NET
- 16. .NET
- 17. .NET 3.5から.NET 2.0への変換
- 18. .net 2.0から.net 4.0への移行
- 19. .net 4.0から4.5へのアップグレードckeditor .net
- 20. .NET Framework 3.0アプリケーション(Windows XP SP3、.NET Framework 4.0)
- 21. .NET正規表現.net C#dataannotations
- 22. .NET 4.5の.NETセキュリティモデル(CAS)の状態は?
- 23. StructureMapとASP .Net Web APIと.Net Framework 4.5
- 24. .NET対応のVisualStudio IDE for .NET/C#
- 25. .NET IoC - .NET Unityの等価コード
- 26. 64ビット.NETのアセンブリロードエラー.NET Informix ADO.NETプロバイダ
- 27. .NETコレクションクラス
- 28. .netコメントシステム
- 29. .Netイベントログ
- 30. .Netデータベースメッセージブローカリング
+1、特に「アイテムはFIFOからデキューされますが、その順序でキューから出て来るものを監視することはできないかもしれません」。 –
多くのありがとうございます。それは間違いなく答えに役立ちます。しかし、そのFIFOがマルチスレッド化すると、どのように役立ちますか?マルチスレッドがアイテムを「レポートする」方法であれば、「TryTake」を順番に実行することもできますか?マルチスレッドの利点は、どのアイテムも同時に取り出して、最初のアイテムを取り出す必要があるだけです(キューの目的を破ることは確かですが、マルチスレッドとデキューを連続して実行するのは必ずしも手に入りません)。 – Kallol
私はScottのコードをチェックし、デキューするTPL呼び出しを削除し、それを順次にしました。パフォーマンスを大幅に節約できます。 TPLでは、i7、クアッドコア、16GBマシンの50Kアイテムのデキューにはほぼ1000msかかりますが、デキューシーケンシャルを実行すると平均23-30ms以内になります。したがって、アイテムはFIFOで検索されるため、同時キューのマルチスレッド化はボトルネックになります。これは、私が助けを求めていた以前の質問、つまり並行キューのデキュー操作でのマルチスレッドの利点 – Kallol