Şafak Gür
Şafak Gür

Reputation: 7345

Is Queue<T>.Enqueue(T) method thread-safe when it is used alone?

Would it be thread-safe if I solely call Enqueue(T) from multiple threads simultaneously and wait for those threads to complete before calling Dequeue() or enumerating the queue?

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());
});

Upvotes: 5

Views: 9845

Answers (4)

Adam Houldsworth
Adam Houldsworth

Reputation: 64487

The documentation also states that instance members of this type are not thread safe (scroll down to the Thread Safety section).

The documentation also states:

A Queue can support multiple readers concurrently, as long as the collection is not modified.

However, this is just a by-product of the fact that concurrent reading does not mutate the list. It does not make the type "thread-safe". Thread-safety is best thought of as offering true support across all actions that define the public contract of the type (in this case, thread-safety in mutating the list also).

More tongue-in-cheek: the implementation of Enqueue doesn't include any thread synchronisation or locking primitives:

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++;
}

So I'm going with "no". There is ConcurrentQueue for multi-threaded support.

Upvotes: 17

usr
usr

Reputation: 171178

This is important: If the docs don't say the queue is thread-safe, it isn't. (And for Queue, they say it is not thread-safe).

Looking at the internals is a weak test: The internals might change any time to a non-thread-safe version.

Don't rely on undocumented properties except under unusual circumstances.

Upvotes: 4

daryal
daryal

Reputation: 14919

I do not think this will be threadsafe since Queue is not thread safe. You are sharing same instance to different threads.

A Queue can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization. http://msdn.microsoft.com/en-us/library/7977ey2c.aspx

Upvotes: 1

BAF
BAF

Reputation: 445

Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

http://msdn.microsoft.com/en-us/library/7977ey2c.aspx

You need to implement your own synchronization (i.e., use lock()), or use ConcurrentQueue (System.Collections.Concurrent).

Upvotes: 0

Related Questions