1

Let's say I have a list in a class which will be used in a multi threading scenario.

public class MyClass
{
     List<MyItem> _list= new List<MyItem>();
     protected object SyncRoot { 
      get {
         return ((IList)_list).SyncRoot;
        }
     }

     public void Execute1()
     {
        lock(SyncRoot)
        {
             foreach(var item in _list) DoSomething(item);
        }
     }

     public void Execute2()
     {
         Item[] list;
         lock(SyncRoot)
         {
            list=_list.ToArray();
         }
           for(var i=0;i<list.Length;i++) DoSomething(list[i]);
      }
}

The method Execute1 is the 'normal' way to enumerate the list in a thread-safe way. But what about Execute2? Is this approach still thread-safe?

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • 1
    No, Execute2 is unsafe if MyItems are reference types (objects), as the list and array both point to the same objects ultimately. – Will Apr 10 '12 at 07:34
  • @Will That's not a problem in this specific scenario as I'm concerned only about the list itself. The objects can handle sync themselves if it's required. – MikeSW Apr 10 '12 at 07:52
  • @HenkHolterman I know I can use any object, but I'm wondering if it's better to use the list's sync object. I mean that's why it's exposed, no?! – MikeSW Apr 10 '12 at 07:53
  • This site has an awesome set of chapters on multi-threading: http://www.albahari.com/threading/ – Will Apr 10 '12 at 08:17

2 Answers2

2

Access to the (copy of the) List is threadsafe in both scenarios. But of course the MyItem elements are not synchronized in any way.

The second form looks a little more expensive but it will allow Add/Remove on the original while the DoSomething()s are running. The array acts like a kind of snapshot, if that matches your requirements it could be useful. Note that you might as well use ToList().

H H
  • 263,252
  • 30
  • 330
  • 514
1

It's safe as long as every other use of _list is also protected with the same lock statement. You are taking exclusive access to the list, copying its contents and then working on the copy (to which you also have exclusive access due to scoping). A bit wasteful at first sight, but a legitimate approach under certain circumstances.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • Yes, add/remove items from list are made using the same lock. However I don't quite grasp why the local list automatically gets exclusive access. – MikeSW Apr 10 '12 at 07:21
  • @MikeSW: Because it's out of scope for everyone else except method `Execute2`. – Jon Apr 10 '12 at 07:27