125
votes

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

3
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
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
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

3 Answers

192
votes

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.

90
votes

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.

31
votes

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.