手动锁定和同步方法之间的区别

时间:2011-05-26 14:16:26

标签: c# .net multithreading locking

这有什么区别:

internal class MyClass
{
    private readonly object _syncRoot = new Object();

    public void DoSomething() 
    {
        lock(_syncRoot)
        {
            ...
        }
    }

    public void DoSomethingElse() 
    {
        lock(_syncRoot)
        {
            ...
        }
    }
}

和此:

internal class MyClass
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    public void DoSomething() 
    {
        ...
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void DoSomethingElse() 
    {
        ...
    }
}

我看到的唯一区别是第一种方法锁定某个私有成员,而第二种方法锁定实例本身(因此它应该锁定实例中的其他所有内容)。是否有任何使用方法的一般建议?我目前在项目中发现了两个具有相似目的的课程,每个课程都采用不同的方法编写。

编辑:

也许还有一个问题。是这样的:

internal class MyClass
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    public void DoSomething() 
    {
        ...
    }
}

完全相同:

internal class MyClass
{
    public void DoSomething() 
    {
        lock(this) 
        {
            ...
        }
    }
}

5 个答案:

答案 0 :(得分:36)

首选方法是首选,因为您可以(并且应该)将_syncRoot设为私有。这降低了死锁的风险。

MethodImplOptions.Synchronized是一个早先雄心勃勃的想法遗留下来的结果,毕竟结果并不那么好。

关于最后一个问题:是的,根据this blog,它们在功能上是等价的(但没有以相同的方式实施)。并且由于死锁情况,不鼓励所有形式的lock(this)。{{1}}。

答案 1 :(得分:13)

结帐http://blogs.msdn.com/b/bclteam/archive/2004/01/20/60719.aspxhttp://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_20926988.html
他们讨论了lock(this)并且不鼓励使用它,因为:

  

完全不相关的代码也可以选择锁定该对象

引自EE:

  

如果锁定对象,则需要访问此特定对象的所有其他线程将等待,直到另一个对象完成。但是,如果将方法标记为已同步,则不会在多个线程上执行此特定方法。 Lock保护对象,Synchronized保护方法。

答案 2 :(得分:8)

快速查看并发现便携式设备不支持MethodImplOptions.Synchronized。

还有一句话:

  

锁定实例或关于   类型,与Synchronized标志一样,   不建议公共类型,   因为你自己以外的代码都可以   锁定公共类型和   实例。这可能会导致死锁   或其他同步问题。

来源:http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions%28v=VS.100%29.aspx

答案 3 :(得分:2)

我认为差异取决于装饰方法中引用的对象。从我读过的,装饰实际上在IL中实现了lock()。

最好的方法是根据需要进行最具体的锁定。

答案 4 :(得分:1)

本文可能会对您有所帮助:http://www.yoda.arachsys.com/csharp/threads/lockchoice.shtml

通常我会避免锁定'this',因为私有锁变量可以提供更好的控制。我建议锁定'this',如果它是一个自定义集合类,就像SyncRoot一样,如果这是必需的。

Hasanain