はじめに
今回はスレッドセーフなコレクションとして知られているConcurrentQueue
について書きたいと思います。
docs.microsoft.com
普通のQueue
とConcurrentQueue
で同じような処理をした際、どのような違いがあるのか見比べていきます。
Queue
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { var queue = new Queue<int>(); // 5個のスレッドで並列に実行 for (int i = 0; i < 5; i++) { _ = Task.Run(() => { for (int j = 0; j < 3; j++) { queue.Enqueue(j); Thread.Sleep(1); } }); } int count = 0; while (count < 15) { int item = default(int); if (queue.Count > 0) { item = queue.Dequeue(); Console.WriteLine(item); count++; } Thread.Sleep(1); } } }
プログラム的には結構動きそうな予感がしますが、実行してみるとめちゃくちゃな結果が出力がされます。
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2
ConCurrentQueue
次にスレッドセーフと呼ばれているConCurrentQueue
を使ってみます。
using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { var queue = new ConcurrentQueue<int>(); // 5個のスレッドで並列に実行 for (int i = 0; i < 5; i++) { _ = Task.Run(() => { for (int j = 0; j < 3; j++) { queue.Enqueue(j); Thread.Sleep(1); } }); } int count = 0; while (count < 15) { int item; if (queue.TryDequeue(out item)) { Console.WriteLine(item); count++; } Thread.Sleep(1); } } }
0 0 0 0 0 1 1 1 1 1 2 2 2 2 2
こちらの出力は理想どおりになっています。
さいごに
普段あまり見慣れないConcurrentQueue
ですが、マルチスレッド処理をする場合にはかなり重宝しそうなコレクションです。
キューは結構こういった使い方もすることも多いと思うので、是非うまく活用してみてください。
ではまた。