134

It is very common to use a private static readonly object for locking in multi threading. I understand that private reduces the entry points to the locking object by tightening the encapsulation and therefore access to the most essential.

But why static?

private static readonly object Locker = new object();

At the end the field is only used within my class only, and I could also just use this instead:

private readonly object Locker = new object();

Any comments?

UPDATE:

As an example I have pasted this code (just an example). I could use static or non-static locker on this and both would work fine. Considering the answer below I should be rather defining my locker like this?

private readonly object Locker = new object();

And here is the code:

    private int _priceA;
    private int _priceB;
    private EventWaitHandle[] _waithandle;
    private readonly IService _service;

//ctor
public ModuleAViewModel(IService service)
    {
        _service = service;
        _modelA = new ModelA();
        _waithandle = new ManualResetEvent[2];
        _waithandle[0] = new ManualResetEvent(false);
        _waithandle[1] = new ManualResetEvent(false);
        LoadDataByThread();
    }


 private void LoadDataByThread()
        {
            new Thread(() =>
                           {
                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceA = _service.GetPriceA();
                                   }
                                   _waithandle[0].Set();
                               }).Start();

                               new Thread(() =>
                               {
                                   lock (Locker)
                                   {
                                       _priceB = _service.GetPriceB();
                                   }
                                   _waithandle[1].Set();
                               }).Start();

                               WaitHandle.WaitAll(_waithandle);
                               PriceA = _priceA;
                               PriceB = _priceB;
                           }).Start();
        }

Thanks

Nerdroid
  • 13,398
  • 5
  • 58
  • 69
Houman
  • 64,245
  • 87
  • 278
  • 460
  • 15
    To my knowledge, static is usually used to make it instance-agnostic. If several instances of "MyWorkerClass" exist, only one can run with the given data at a time (assuming they all use shared resources). – Brad Christie Feb 19 '11 at 20:01
  • 2
    The edit lacks an important detail: where are `_service` and `_waithandle` located? instance? static? other? That *could*, for example, be deliberately synchronizing access to a remote server... – Marc Gravell Feb 19 '11 at 20:15
  • right, with the second edit : yes, from this end of things you could lock per instance. There *may* have been reasons to make it static, though - if the original dev wanted (as mentioned) to synchronize access so that the server only gets one request at once from this AppDomain... I can't know whether that is the case, or whether it was just accidental. – Marc Gravell Feb 19 '11 at 20:32

3 Answers3

204

It isn't "very common to use a private static readonly object for locking in multi threading" - rather, it is common to use a lock at the appropriate / chosen granularity. Sometimes that is static. More often, IMO, it isn't - but is instance based.

The main time you see a static lock is for a global cache, or for deferred loading of global data / singletons. And in the latter, there are better ways of doing it anyway.

So it really depends: how is Locker used in your scenario? Is it protecting something that is itself static? If so, the lock should be static. If it is protecting something that is instance based, then IMO the lock should also be instance based.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 28
    Could you give more detail on a better way to deferred loading of global data? – bizi Jul 31 '13 at 00:19
  • 2
    I always use a static/volatile because if there are several places where it is instance based I still would want to control my method/variable being accessed in a thread safe way. Many instances may be accessing the same resources and I want to control that. i too would like to see the better of doing this. You have a great rep and I am sure your reply will be equally great for me to adopt. Please reply? – Andrew Simpson Dec 17 '17 at 09:52
93

It doesn't have to be static, in fact sometimes it should not be static.

The variable should live in the same scope as the methods where you use it for locking. If the methods are static, the variable should be static, and if the methods are instance methods, the variable should be an instance varible.

A static variable will still work when used to lock in an instance method, but then you will be locking too much. You will lock all methods in all instances, not just the methods in the same instance.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 3
    @radarbob - Minor detail: You won't _lock all methods_ you just take a lock that more clients could be interested in. Methods are never locked, it's just that the mutex has been taken. – Emond Apr 09 '14 at 12:39
  • 1
    I suspect phrasing of this answer could be misleading - locking should not have to do anything with scope of methods - it should only be concerned with scope of *shared data* accessed in those methods. Instance method may not access any shared data (and hence no need for locking), may access static shared data (and hence need static lock, also refactoring may be good idea instead), same for static... – Alexei Levenkov Dec 22 '17 at 16:22
  • @AlexeiLevenkov: You are right that the scope should actually be decided by whether the data is static or not, but the scope of the methods should also be decided by that, so it all fits together. Instance data normally doesn't need locking, but if the instance is shared between threads then you would need locking. – Guffa Dec 23 '17 at 15:34
  • Sometimes you may be using a non static method to operate to a rather global level, such as the windows registry, in that case you should use static lock to avoid any two instance to try to operate at the same time on the same registry. – Sergio Prats Mar 21 '23 at 15:29
32

The scope and lifetime of a lock can/should depend on the 'thing' you want to lock. Static locks are mostly used to lock static things.

Emond
  • 50,210
  • 11
  • 84
  • 115
  • 3
    Minor detail: The lock isn't static, the object that you use to identify the lock is static. Another minor detail: You don't lock "things". – Guffa Apr 09 '14 at 13:21
  • 2
    Yes, I think if we tried to lock the wrong "things" up, they may be too big and strong, and one day escape. – ProfK Nov 27 '15 at 20:07
  • 13
    @Guffa That's odd, in a comment above you rightly said: "You are just overcomplicating things," now I see 1 min before saying that, it seems you were overcomplicating things :) – Nicholas Petersen Jul 25 '16 at 16:59