I noticed that you can call Queue.Synchronize to get a thread-safe queue object, but the same method isn't available on Queue<T>. Does anyone know why? Seems kind of weird.
Update - in .NET 4, there now is ConcurrentQueue<T>
in System.Collections.Concurrent, as documented here http://msdn.microsoft.com/en-us/library/dd267265.aspx. It's interesting to note that its IsSynchronized method (rightly) returns false.
ConcurrentQueue<T>
is a complete ground up rewrite, creating copies of the queue to enumerate, and using advanced no-lock techniques like Interlocked.CompareExchange()
and Thread.SpinWait()
.
The rest of this answer is still relevant insofar as it relates to the demise of the old Synchronize() and SyncRoot members, and why they didn't work very well from an API perspective.
As per Zooba's comment, the BCL team decided that too many developers were misunderstanding the purpose of Synchronise (and to a lesser extent, SyncRoot)
Brian Grunkemeyer described this on the BCL team blog a couple of years back: http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx
The key issue is getting the correct granularity around locks, where some developers would naively use multiple properties or methods on a "synchronized" collection and believe their code to be thread safe. Brian uses Queue as his example,
if (queue.Count > 0) { object obj = null; try { obj = queue.Dequeue();
Developers wouldn't realize that Count could be changed by another thread before Dequeue was invoked.
Forcing developers to use an explicit lock statement around the whole operation means preventing this false sense of security.
As Brian mentions, the removal of SyncRoot was partly because it had mainly been introduced to support Synchronized, but also because in many cases there is a better choice of lock object - most of the time, either the Queue instance itself, or a
private static object lockObjForQueueOperations = new object();
on the class owning the instance of the Queue...
This latter approach is usually safest as it avoids some other common traps:
As they say, threading is hard, and making it seem easy can be dangerous.
You might find the Parallel CTP worth checking out; here's a blog entry from the guys who are putting it together that's pretty topical:
Enumerating Concurrent Collections
It's not quite the same thing, but it might solve your bigger problem. (They even use Queue<T>
versus ConcurrentQueue<T>
as their example.)
There is one now, in .Net 4.0:
ConcurrentQueue<T>
in System.Collections.Concurrent
http://msdn.microsoft.com/en-us/library/dd267265.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With