tags:

views:

151

answers:

4

What is the difference (if any) between using

void MethodName()
{
    lock(this)
    {
        // (...)
    }
}

or

private object o = new object();
void MethodName()
{
    lock(o)
    {
        // (...)
    }
}

?

Is there a difference in performance? Style? Behaviour?

+8  A: 

The difference is that anyone can lock on your instance, but only you can lock on a private object.

This helps prevent deadlocks.

For example:

Let's say that Microsoft used lock(this) in the Control class.

Then, if someone else locks on a Control instance, his lock would prevent the code in Control from running, which is not what he wants.

This is particularly bad if you lock on types that are shared across AppDomains

SLaks
Nice point about weak identity locks.
Steven Sudit
+11  A: 

lock(this) will lock on the "current" object.

Locking on "this" is usually a bad idea as it exposes the lock to other code; I prefer to have a readonly field, like this:

public class Foo
{
    private readonly padlock = new object();

    public void SomeMethod()
    {
        lock(padlock)
        {
            ...
        }
    }
}

That way all calls to SomeMethod (and anything else in Foo which locks on padlock) will lock on the same monitor for the same instance of Foo, but nothing else can interfere by locking on that monitor.

In reality, unless you're dealing with "rogue" code, it's unlikely that other code will actually lock on the reference to an instance of Foo, but it's a matter of encapsulation.

Jon Skeet
I'd add that the real advantage of this isn't just in stopping rogue (or incompetent) code from deadlocking you, but for allowing wrapping. You can expose your locker object as a SyncLock property, or expose the SyncLock property of the object you're wrapping. This way, locks on the wrapping instance become locks on the wrapped instance.
Steven Sudit
+1  A: 

There is a difference in scope and there can be a difference in behavior (incidentally, using "this" is not recommended by MS


// in this case, your lock object is public, so classes outside of this can lock on the same thing
lock(this) {}

// in this case, your lock is private, and only you can issue a lock statement against it
private lockobj = new object()
..
lock(this.lockobj) {}

// this one is WRONG -- you willget a new object instance every time, so your lock will not provide mutual exclusion
void SomeMethod()
{
  // using a local variable for a lock -- wrong
  object obj = new object();
  lock(obj) {}
}

JMarsch
+1  A: 

The pattern I usually follow is this, for a class declared static....

public static class SomeClass{
    private static objLock = new object();
    ....
    public static object SomeProperty{
       get{ 
           lock(objLock){
             // Do whatever needs to be done
           }
       }
       set{
           lock(objLock){
           }
       }
    }
}

Likewise for a normal class I would follow this pattern:

public class SomeClass{
    private readonly objLock = new object();
    ....
    public object SomeProperty{
       get{ 
           lock(objLock){
             // Do whatever needs to be done
           }
       }
       set{
           lock(objLock){
           }
       }
    }
}

In that way, no one can lock on my instance and will prevent deadlocks from occuring...

Edit: I have amended this article to make it clearer with regards to the code where the basis of the static lock would be used and for a normal class... Thanks Steven and Dalle for their point outs...

Hope this helps, Best regards, Tom.

tommieb75
Are you sure you intended a `static` lock?
dalle
@dalle: Yes, I would use that in a static class, I would do the following, 'private readonly object objLock = new object()' within a normal class. Does this answer your question? :)
tommieb75
It wasn't clear from your example that you were in a static class. Now that you specified this, it does make sense for the locker to be static, as well. Your naming conventions make it harder to understand your intent, as they violate .NET standards.
Steven Sudit
@Steven: I will amend the answer accordingly....
tommieb75