Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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

(I assume you mean Queue<T> for the second one.)

I can't specifically answer the question, except that the IsSynchronized and SyncRoot properties (but not Synchronise() explicitly) are inherited from the ICollection interface. None of the generic collections use this and the ICollection<T> interface does not include SyncRoot.

As to why it is not included, I can only speculate that they weren't being used either in the way intended by the library designers or they simply weren't being used enough to justify retaining them in the newer collections.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top