469,272 Members | 1,439 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,272 developers. It's quick & easy.

What is the difference between SyncRoot and Synchronized method in Queue?

Hi

I often use Queue.Synchronized method to create a queue for multithread writing. I also know I could use SyncRoot and lock to write Queue. Could anyone here please explain to me the pros and cons between those two approaches
Thanks a lo

Chris
Nov 15 '05 #1
4 10505
The Synchronized wrapper gives you the *illusion* that your code is thread
safe. As soon as you start writing code like:

for (int i = 0; i < collection.Count; i++)
DoSomething(collection[i])

you take chances because another thread may modify the collection (delete an
element for example) between the time you evaluate the Count property and
the time you call the indexer (so you may get an ArrayOutOfBoundException).

With SyncRoot, you use a different pattern, you synchronize in the "caller"
rather than in the "callee". This is more work because you have to worry
about synchronization in all the places where you use the collection. But on
the other hand, this forces you into putting more thought into your
synchronization strategy, and if you do it right, you will write correct
code.

For example, if you don't use the Synchronized wrapper, you have to write
the for loop above as:

lock (collection.SyncRoot)
{
for (int i = 0; i < collection.Count; i++)
DoSomething(collection[i])
}

This loop is safe (of course, I assume that you also have locks around every
piece of code that accesses the collection).

The SyncRoot strategy is usually more efficient too, because you don't
synchronize every call to the collection, you synchronize around blocks that
may perform several calls (the original Java collection API -- JDK 1.1 --
was terrible here because the collections were always completely
synchronized, even when you used them in single-thread scenarios).

Of course, your (high level) APIs should not expose the collections. The
collections should always be private stuff that your class uses to do its
own bookkeeping. If your APIs expose unsynchronized collections, you force
every piece of code that uses your class to do its own synchronization, and
you are in for big trouble (perf problems, race condition problems,
deadlocks).

So, my recommendation it to use SyncRoot and "external" locking rather than
the Synchronized wrapper, and to encapsulate the locking logic in classes
that don't expose their internal collections directly.

Bruno.
"chrisben" <an*******@discussions.microsoft.com> a écrit dans le message de
news:7B**********************************@microsof t.com...
Hi,

I often use Queue.Synchronized method to create a queue for multithread writing. I also know I could use SyncRoot and lock to write Queue. Could
anyone here please explain to me the pros and cons between those two
approaches? Thanks a lot

Chris

Nov 15 '05 #2
> I think I do get the answers I was looking for. In fact, I have thought
even SyncRoot is not thread safe for interator.
Thanks


It's safe as long as all threads are locking on SyncRoot (which is really
pointing to "this" of the collection instance). So if your iterating, you
don't want another thread to be removing items at the same time - and they
can't if the other thread syncs on same lock.

The sync wrapper, truely is just a simple wrapper that itself syncs on the
SyncRoot of the Queue instance. Something very close to this:

private class SynchronizedQueue
{
private Queue q;
private object syncRoot;

internal SynchronizedQueue(Queue q)
{
this.q = q;
this.syncRoot = q.SyncRoot;
}

public override object Dequeue()
{
lock(syncRoot)
{
obj = q.Dequeue();
return obj;
}
}
}

Your effectively doing this when locking on the SyncRoot before your Gets
and Puts. Your locking the same var twice when using both SyncRoot and the
wrapper. If you can gaurentee yourself all methods will lock on SyncRoot,
then the wrapper is not needed and pretty much redundant and a bit slower
because of the twice-locked deal. hth
Cheers!

--
William Stacey, MVP

Nov 15 '05 #3
Thanks.

Just one additional note:

The Synchronized wrapper may be interesting with very simple collections
like queues and stacks. If all you do with the collection is a set of
Enqueue/Dequeue or Push/Pop that only need individual synchronization, the
wrapper will be more practical, but a soon as you start doing more complex
things with collections (like iterating on their contents), you should use
SyncRoot synchronization.

Bruno.

"chrisben" <an*******@discussions.microsoft.com> a écrit dans le message de
news:35**********************************@microsof t.com...
Thanks Bruno,

I think I do get the answers I was looking for. In fact, I have thought even SyncRoot is not thread safe for interator. Thanks

Chris

Nov 15 '05 #4
Thanks for your advices.
Nov 15 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Rich Sienkiewicz | last post: by
1 post views Thread by Frank Rizzo | last post: by
6 posts views Thread by rmunson8 | last post: by
7 posts views Thread by Alan Wang | last post: by
7 posts views Thread by TS | last post: by
19 posts views Thread by =?ISO-8859-1?Q?Nordl=F6w?= | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.