はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【C#】ConcurrentQueue<T>を使ってみる

はじめに

今回はスレッドセーフなコレクションとして知られているConcurrentQueueについて書きたいと思います。
docs.microsoft.com

普通のQueueConcurrentQueueで同じような処理をした際、どのような違いがあるのか見比べていきます。

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ですが、マルチスレッド処理をする場合にはかなり重宝しそうなコレクションです。

キューは結構こういった使い方もすることも多いと思うので、是非うまく活用してみてください。

ではまた。