What is the difference between lock (this) and lock (thisLock)?

advertisements

I'm reading lock Statement (C# Reference) where I saw this code:

class Account
{
    private Object thisLock = new Object();

    //...

    int Withdraw(int amount)
    {
        lock (thisLock)
        {
           //....
        }
    }

    //...
}

I'm wondering if it would make any difference if we write lock(this) instead of lock(thisLock) in the above example. Please see the complete example if your answer depends on it.

If you think there is indeed some difference between lock(this) and lock(thisLock) , then please help me understanding the difference with all important points. In particular, what does each exactly mean?


The difference stems from the fact that lock, if misused, can result in thread deadlock. If the lock target's visibility is unknown to you (i.e., you cannot be 100% certain who has a reference to the target and if/when they might lock it), then you cannot really know if the application might experience a deadlock.

For this reason it's customary to lock on a private member: since it's private and it's in your code, you do know that noone else can lock it.

Of course all this is a purely academic difference most of the time (usually people don't go around locking random objects), but it's a good defensive coding practice.

The page you link to states:

In general, avoid locking on a public type, or instances beyond your code's control. The common constructs lock (this), lock (typeof (MyType)), and lock ("myLock") violate this guideline:

lock (this) is a problem if the instance can be accessed publicly.

Because someone else might lock the instance using a reference they have, and your code that does lock(this) will of course not expect that. Example on IDEone (see line 26).

lock (typeof (MyType)) is a problem if MyType is publicly accessible.

A variation of the above, if the type is visible to other code then you might end up trying to lock the same instance as that code (typeof returns singleton instances).

lock("myLock") is a problem because any other code in the process using the same string, will share the same lock.

Another variation: due to string interning, code ends up trying to lock the same instance.

Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.