Reputation: 7345
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
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
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
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
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