SyncRoot implementation for an IList

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matt

    SyncRoot implementation for an IList

    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.Sy ncRoot ) {
    // 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
  • Nicholas Paldino [.NET/C# MVP]

    #2
    Re: SyncRoot implementation for an IList

    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.


    --
    - Nicholas Paldino [.NET/C# MVP]
    - nicholas.paldin o@exisconsultin g.com

    "Matt" <ktrvnbq02@snea kemail.com> wrote in message
    news:553872e9.0 309020536.4bf9a 22e@posting.goo gle.com...[color=blue]
    > 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.Sy ncRoot ) {
    > // 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[/color]


    Comment

    • Magnus Lidbom

      #3
      Re: SyncRoot implementation for an IList


      "Matt" <ktrvnbq02@snea kemail.com> wrote in message
      news:553872e9.0 309020536.4bf9a 22e@posting.goo gle.com...[color=blue]
      > Hello all,
      >
      > I have written a collection class that implements IList. The class
      > currently uses an ArrayList for its internal storage.[/color]

      <snip>
      [color=blue]
      > 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?[/color]
      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.

      [color=blue]
      > 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.:[/color]
      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









      Comment

      Working...