Queue <T> .Enqueue(T)方法单独使用时是否是线程安全的?

Şaf*_*Gür 4 c# queue asynchronous thread-safety

如果我Enqueue(T)同时从多个线程调用并在调用Dequeue()或枚举队列之前等待这些线程完成,那么它是否是线程安全的?

var queue = new Queue<int>();
Action enqueue = () =>
{
    for (int i = 0; i < 100000; i++)
        queue.Enqueue(i);
};

var tasks = new[]
{
    new Task(enqueue),
    new Task(enqueue),
    new Task(enqueue)
};
foreach (var task in tasks)
    task.Start();

Task.Factory.ContinueWhenAll(tasks, t =>
{
    while (queue.Count > 0)
        Console.WriteLine(queue.Dequeue());
});
Run Code Online (Sandbox Code Playgroud)

Ada*_*rth 14

该文档还指出此类实例成员不是线程安全的(向下滚动到"线程安全"部分).

文件还说明:

只要不修改集合,队列就可以同时支持多个读取器.

然而,这只是并发读取不会改变列表这一事实的副产品.它并没有使型"线程安全的".线程安全最好被认为是为定义类型的公共契约的所有操作提供真正的支持(在这种情况下,线程安全也在改变列表).

更多的诙谐:Enqueue的实现不包括任何线程同步或锁定原语:

public void Enqueue(T item)
{
    if (this._size == this._array.Length)
    {
        int num = (int)((long)this._array.Length * 200L / 100L);
        if (num < this._array.Length + 4)
        {
            num = this._array.Length + 4;
        }
        this.SetCapacity(num);
    }
    this._array[this._tail] = item;
    this._tail = (this._tail + 1) % this._array.Length;
    this._size++;
    this._version++;
}
Run Code Online (Sandbox Code Playgroud)

所以我选择"不".有ConcurrentQueue对多线程的支持.

  • +1:可以找到多线程入队时发生的事情的实际示例[这里](http://stackoverflow.com/a/11981777/572644).请注意非确定性行为. (2认同)