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