Michael said:
What is the recommended pattern for implementing a synchronized
(thread-safe) class that inherits from Collection<T>? For example, I want
to implement a SyncRoot property [of type
System.Threading.ReaderWriterLock]. I do see where I can override
(protected) the methods InsertItem, RemoveItem, ClearItems, and SetItem.
However, I do not see an override for GetItem.
I have an issue with the whole business of synchronized collections
altogether. Using or changing a collection usually requires it to be
user-controlled temporally immutable across invocations of methods anyway.
For me, synchronization of methods on collections is mostly an
*implmentation* issue, which an implementer can use to prevent the
data-structure from corruption from multiple threads operating on the
structure at once.
Locking for iteration and actions depending on containment, cannot
usually be solved by synchronized methods, it requires block-level
locking to guarantee synchronization between invocations of methods:
lock ( collection ) { // or collection.SyncRoot in .NET1
int count = collection.Count;
foreach ( object t in collection )
...;
}
lock ( collection ) {
if ( t.Contains(x) )
...;
}
WRT, SyncRoot:
I can't understand the "lock-counting" arguments, I don't see that they
come into the discussion at all. It's much more important whether there
is a protocol for passing a collections mutability around. That said,
note that if the client properly locks before using a collection there
is *one* lock-attempt for each "conversation" between a client and a
collection.
In .NET1, I had lots of adapters for collections, which would simply
pass their inner.SyncRoot for their own SyncRoot. In .NET2, it now
requires an external protocol to make that work.
It's not that I'm too glad of SyncRoot, but I was glad *something* was
there.
SyncRoot only allowed lock/Monitor. I would prefer a protocol where you
could allocate Read and/or Write permission, and obtain an object which
would guarantee you that permission, and associated guaratees on
synchonization of read and writes, untill you Dispose() that object.