1

Please explain the difference between these two types of locking.

I have a List which I want to access thread-safe:

var tasks = new List<string>();

1.

var locker = new object();
lock (locker)
{
    tasks.Add("work 1");
}

2.

lock (tasks)
{
    tasks.Add("work 2");
}

My thoughts:

  1. Prevents two different threads from running the locked block of code at the same time.

But if another thread runs a different method where it tries to access task - this type of lock won't help.

  1. Blocks the List<> instance so other threads in other methods will be blocked untill I unlock tasks.

Am I right or mistaking?

Andrew
  • 153
  • 4
  • 16
  • 1
    See [this question](http://stackoverflow.com/questions/6891711/difference-between-lockthis-and-a-lock-on-static-object?rq=1) and the links on the post. – gunr2171 Jul 22 '14 at 20:03
  • *Your thoughts* are not correct. There is no such thing like *Blocking the instance*. `Lock` keyword is implemented by *Monitor.Enter* and *Monitor.Exit* See http://stackoverflow.com/questions/4978850/monitor-vs-lock – EZI Jul 22 '14 at 20:08

2 Answers2

2

(2) only blocks other code that explicitly calls lock (tasks). Generally, you should only do this if you know that tasks is a private field and thus can enforce throughout your class that lock (tasks) means locking operations on the list. This can be a nice shortcut when the lock is conceptually linked with access to the collection and you don't need to worry about public exposure of the lock. You don't get this 'for free', though; it needs to be explicitly used just like locking on any other object.

Dan Bryant
  • 27,329
  • 4
  • 56
  • 102
  • I still can't understand... If two threads run different methods from different classes and both are trying to access `static List<>` (from the third class) - what is the best way to provide thread-safety? 1) lock List object; 2) lock specially created `var locker = new object()` (different lockers for different classes) 3) lock one general `locker` in both methods. ? – Andrew Jul 22 '14 at 20:21
  • 1
    @Andrew, attempting to lock on a static list that is publicly visible is dangerous territory. You can have them all agree to lock on the same list instance when performing operations, but it only takes one uncooperative class to ruin the party for everybody. You may want to consider encapsulating the thread-safe collection access into a different class entirely that all classes get a reference to, rather than using a static collection. – Dan Bryant Jul 22 '14 at 20:23
  • 1
    @Andrew, regarding (2), you definitely don't want different lockers for different classes, as they are using the same collection and can potentially corrupt its state. – Dan Bryant Jul 22 '14 at 20:24
1

They do the same thing. Any other code that tries to modify the list without locking the same object will cause potential race conditions.

A better way might be to encapsulate the list in another object that obtains a lock before doing any operations on the underlying list and then any other code can simple call methods on the wrapper object without worrying about obtaining the lock.

mclaassen
  • 5,018
  • 4
  • 30
  • 52
  • So if both options are equal, what is the best way: to lock specially created object (like `locker`) or to lock collection itself ? – Andrew Jul 22 '14 at 20:05
  • @Andrew There would be no difference if the list itself and locker object had the same scope. However if the locker object was not visible to some other code that wanted to perform thread safe operations it would not be able to obtain the lock. – mclaassen Jul 22 '14 at 20:07
  • I still can't understand... If two threads run different methods from different classes and both are trying to access `static List<>` (from the third class) - what is the best way to provide thread-safety? 1) lock List object; 2) lock specially created `var locker = new object()` (different lockers for different classes) 3) lock one general `locker` in both methods. ? – Andrew Jul 22 '14 at 20:27