SyncRoot implementation for an IList

M

Matt

Hello all,

I have written a collection class that implements IList. The class
currently uses an ArrayList for its internal storage.

I am somewhat confused as to how I should implement the SyncRoot
property on my class. The MSDN documentation seems quite evasive on
the subject:

For collections whose underlying store is not publicly available,
the expected implementation is to return the current instance. Note
that the pointer to the current instance might not be sufficient for
collections that wrap other collections; those should return the
underlying collection's SyncRoot property.

[...]

In the absence of a Synchronized method on a collection, the
expected usage for SyncRoot looks like this:

ICollection MyCollection = ...
lock( MyCollection.SyncRoot ) {
// Some operation on the collection, which is now thread-safe.
}

This begs the question: what if I were to modify my class later, say
to require another object be updated in sync with the ArrayList? I
wouldn't then be able to rely on the ArrayList's SyncRoot, so I would
have to either return the current instance, or have another object to
lock on?

Then, having chosen *what* to return for SyncRoot, do I need to ensure
that every method that could modify my collection first locks on
SyncRoot? e.g.:

lock ( this.SyncRoot )
{
// modify own state
}

It's quite unlikely that this will ever become an issue with my class
due to the way it is used in the application. However, I'd really like
to understand this point (and I hate leaving things half-done ;)


Regards,

Matt
 
N

Nicholas Paldino [.NET/C# MVP]

Matt,

You are pretty much correct. You could always return the SyncRoot of
the underlying ArrayList, but like you said, you might swap it out.
However, if you implement it the way that you mentioned (locking on the
SyncRoot property when accessing), then you would only have to change the
implementation of the SyncRoot property when you swap out the ArrayList.
Personally, I would store an object reference (to a regular instance of type
object) and return that, locking on that when you access any item in the
collection.

Hope this helps.
 
M

Magnus Lidbom

Matt said:
Hello all,

I have written a collection class that implements IList. The class
currently uses an ArrayList for its internal storage.

This begs the question: what if I were to modify my class later, say
to require another object be updated in sync with the ArrayList? I
wouldn't then be able to rely on the ArrayList's SyncRoot, so I would
have to either return the current instance, or have another object to
lock on?
Assuming the other object is hidden in your collection class, the ArrayList's
SyncRoot would work fine.

The idea behind always using the wrapped containers SyncRoot is that any
reference to any instance in a chain of "wrappings" will return the same
object to lock on, thereby ensuring correct synchronization of the collection
that actually holds the data when locking on SyncRoot, regardless of which
wrapper it's accessed through. I'd make very sure that there is absolutely no
way there can be a reference to the internal ArrayList outside of your
collection class before you decide on having SyncRoot return another object.
No initializer method or constructor taking an ArrayList without cloning it,
no accessor properties or methods, etc etc.

Then, having chosen *what* to return for SyncRoot, do I need to ensure
that every method that could modify my collection first locks on
SyncRoot? e.g.:
Only if your collection is used exclusively in a multithreaded context,
otherwise you should write a separate synchronized wrapper. Don't assume you
only need to lock to write either. That'll get you in a lot of trouble.

Rotor and Mono contain plenty of instructional code in their implementations
of the .Net framework's collection classes. Have a look.

/Magnus Lidbom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top