Why does the lock object have to be static?

Houman picture Houman · Feb 19, 2011 · Viewed 71.3k times · Source

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? (Sorry I have an interview next week and need to know every detail :)

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

Answer

Marc Gravell picture Marc Gravell · Feb 19, 2011

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.