19

I would like to know if there are any guidelineswhich a developer should follow as to when (and where) to place locks.

For instance: I understand that code such as this should be locked, to avoid the possibility of another thread changing the value of SomeHeapValue unexpectedly.

class Foo
{
  public SomeHeapObject myObject;
  public void DoSummat(object inputValue_)
  {
    myObject.SomeHeapValue = inputValue_;
  }

}

My question is, however, how deep does one go with the locking? For instance, if we have this code:

class Foo
{
  public SomeHeapObject myObject;
  public void DoSummat(object inputValue_)
  {
    myObject.SomeHeapValue = GetSomeHeapValue();
  }

}

Should we lock in the DoSummat(...) method, or should we lock in the GetSomeHeapValue() method?

Are there any guidelines that you all keep in mind when strcturing multi-threaded code?

miguel
  • 2,871
  • 4
  • 24
  • 33

3 Answers3

24

The best guide for locking and threading I found, is this page (this is the text I consult when working with locking and threading):

http://www.albahari.com/threading/

You want the paragraph "Locking and Thread Safety", but read the rest as well, it is very well written.

funie200
  • 3,294
  • 5
  • 19
  • 31
user218447
  • 649
  • 4
  • 5
  • 1
    thanks that is useful...but why do all examples use static member variables? there are issues with thread-safety in class member variables as well, right? – miguel May 06 '10 at 09:28
  • @miguel: it is possible to lock instance member by using "lock(this)", explanation and Example2 on this page provide more details: http://msdn.microsoft.com/en-us/library/c5kehkcz%28VS.71%29.aspx. I think that on Albahari site he is using static because then he does not have to make an instance of a class, which makes his examples shorter. – user218447 May 06 '10 at 11:42
  • @miguel: your lock object needs to be shared across threads to be usable, and static is a clean and easy way to do this. Static is not inherently evil, just misused like the globals of old. – Ed Power May 06 '10 at 16:14
  • Another reason for concentrating on statics, is that there's a simple way to make any instance member free from threading concerns - simply never expose it to more than one thread. This is also the reason while most BCL classes are not thread-safe for instance members except a few classes specifically intended for thread-related tasks - why make everyone pay the cost of making something threadsafe if it might never be used that way, but likewise most BCL classes are threadsafe in static members. – Jon Hanna Aug 22 '12 at 19:12
  • @user218447 where exactly is this fragment "Locking and Thread Safety" ? I do not find it on that website – Eru Apr 20 '21 at 08:17
3
  • Lock as little as possible, but as much as needed.

  • Avoid locks when possible - in .NET 4.0 there are alternatives that are not causing a context switch.

  • Try not to lock multiple times. Structure your API accordingly. For example a queue. DeQueue - make an alternative DeQueue(int amount) that can dequeue many items with one lock.

Steven
  • 159,023
  • 23
  • 313
  • 420
TomTom
  • 1
  • 10
  • 85
  • 146
1

Here are some guidelines, aimed for developers relatively novice in multithreading:

  1. Identify the mutable¹ shared² state of your program. Which mutable variables, objects, properties and fields can be accessed by more than one threads during the lifetime of the application, either concurrently or sequentially?

  2. Protect all access to the mutable shared state using a lock. Both write and read operations should be protected. A single unprotected entry point to the mutable shared state of your program is enough to invalidate your locking scheme, and make the behavior of your program undefined.

  3. Use a single locker object to protect all of the mutable shared state. Use multiple lockers only if each locker protects completely isolated islands of mutable shared state.

  4. Release the lock as soon as possible. Make sure that the protected regions include operations only on state that is shared and mutable. Don't do anything unrelated to this state inside these regions.

If you follow these guidelines you'll be able to reason about the correctness of your program, and your program will perform reasonably well.

All of these guidelines are bendable, and experts in multithreading can get away by not following them in all occasions, for performance, convenience or other reasons. But the experience required before being able to judge correctly whether it's safe to bend any of these guidelines is huge. So be careful not to become overconfident with yourself too early!

¹ Changeable, not read-only.
² Shared by multiple threads.

Theodor Zoulias
  • 24,585
  • 5
  • 40
  • 69