锁定关键字需要传递什么参数?

8

What is the difference (if any) between using

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

或者

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

性能、样式、行为有区别吗?

4个回答

17

lock(this) 会锁定“当前”对象。

在“this”上加锁通常是不好的做法,因为它会将锁暴露给其他代码;我更喜欢使用只读字段,像这样:

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

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

这样一来,所有对SomeMethod的调用(以及Foo中任何其他在padlock上锁定的内容)都将在同一个监视器上为Foo的同一个实例进行锁定,但其他任何东西都不能通过锁定该监视器干扰。

实际上,除非你正在处理“流氓”代码,否则很少有其他代码会实际锁定Foo实例的引用,但这是封装的问题。


1
我想补充一下,这个真正的优势不仅在于防止流氓(或无能)代码使您死锁,而是允许包装。您可以将您的锁对象公开为SyncLock属性,或者公开您正在包装的对象的SyncLock属性。这样,对包装实例的锁定变为对包装实例的锁定。 - Steven Sudit
“padlock” 似乎缺少类型声明。 - Dan Bechard

11

区别在于任何人都可以锁定您的实例,但只有您可以锁定私有对象。

这有助于防止死锁。

例如:

假设Microsoft在Control类中使用了lock(this)

然后,如果其他人锁定了一个Control实例,他的锁将防止Control中的代码运行,这不是他想要的。

如果您在跨AppDomains共享的类型上进行锁定,那么情况就会变得特别糟糕。


3
我通常遵循以下模式,对于一个声明为static的类...

public static class SomeClass{
    private static object objLock = new object();
    ....
    public static object SomeProperty{
       get{ 
           lock(objLock){
             // 做必要的事情
           }
       }
       set{
           lock(objLock){
           }
       }
    }
}

对于普通类,我会遵循这个模式:

public class SomeClass{
    private readonly object objLock = new object();
    ....
    public object SomeProperty{
       get{ 
           lock(objLock){
             // 做必要的事情
           }
       }
       set{
           lock(objLock){
           }
       }
    }
}

通过这种方式,没有人能够锁定我的实例,并且可以防止死锁的发生...

编辑: 我已经修改了这篇文章,以使代码更明确,其中基础是使用static锁和普通类... 感谢StevenDalle的指出...


1
你确定你想要一个 static 锁吗? - dalle
@dalle:是的,我会在静态类中使用它,我会在普通类中执行以下操作:'private readonly object objLock = new lock()'。这回答了你的问题吗? :) - t0mm13b
从你的示例中并不清楚你在一个静态类中。既然你指定了这一点,那么把储物柜设为静态的确是有意义的。你的命名规范使人难以理解你的意图,因为它们违反了.NET标准。 - Steven Sudit

1

作用域有所不同,行为也可能有所不同(顺便提一下,MS不建议使用“this”)


// 在这种情况下,您的锁对象是公共的,因此在外部类中可以锁定相同的内容
lock(this) {}
// 在这种情况下,您的锁是私有的,只有您才能对其发出锁定语句 private object lockobj = new object() .. lock(this.lockobj) {}
// 这个是错误的--每次都会得到一个新的对象实例,因此您的锁将无法提供互斥 void SomeMethod() { // 使用本地变量进行锁定--错误 object obj = new object(); lock(obj) {} }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接