lock语句使用什么类型的锁定机制

时间:2012-07-06 12:08:08

标签: c# .net multithreading locking

c#lock关键字是否使用“让步”,“自旋锁定”或混合方法来处理争用?

到目前为止,我对.net锁定语句的搜索没有找到答案。 如果我找到了,我会发布。 到目前为止,我所能找到的只是When should one use a spinlock ...,并且Mecki接受了一个措辞谨慎的答案。

但我正在寻找关于.net / c#的一些明确的答案或文件,如果有人的话。

3 个答案:

答案 0 :(得分:9)

以下代码:

lock (_syncRoot)
{
    // Do stuff
}

由编译器翻译为:

Monitor.Enter(_syncRoot)
try
{
    // Do stuff
}
finally
{
    Monitor.Exit(_syncRoot);
}

这是天真的(和旧的)实现,实际上在.NET 4.0中,实现或多或少都是这样的(参见Eric's blog以获得完整参考):

bool locked = false;
try
{
    Monitor.Enter(_syncRoot, ref locked);
}
finally
{
    if (locked)
        Monitor.Exit(_syncRoot);
}

<强> EDITED

那说问题是 Monitor.Enter()如何工作?嗯,默认的Mono实现使用信号量获取锁,但Microsoft .NET实现的行为不同。

我正在阅读 Concurrent Windows Programming (由Joe Duffy撰写)当一段确实引起我的注意时,我的第一个回答说“不,它不使用旋转,因为性能可能不太好案件”。正确答案是“是的,.NET Monitor使用旋转”。 .NET Monitor和Windows Critical Sections都会在回退到内核对象的真正等待之前执行短暂旋转。这种算法被称为“两阶段锁定协议”,它是合适的,因为上下文切换和内核转换非常广泛,在多处理器上,旋转可以避免这两种情况。

此外,请不要忘记这些是实现细节,并且可以在任何版本中进行更改(或者由于JIT编译器,算法可能因不同的硬件而有所不同)。

答案 1 :(得分:1)

lock (obj)
{
}

只是Monitor Enter的语法糖,最后一次尝试......

Monitor.Enter(obj);
try
{
}
finally
{
    Monitor.Exit(obj);
}

现在它是little better(感谢马克和阿德里亚诺让我保持最新状态。)

bool locked = false;  
try  
{  
    Monitor.Enter(_syncRoot, ref locked);  
}  
finally  
{  
    if (locked)  
        Monitor.Exit(_syncRoot);  
} 

答案 2 :(得分:0)

这是Microsoft文档说lock()包装Monitor.Enter / Exit

“使用C#lock语句,它在try ... finally块中包含Enter和Exit方法。”

来自http://msdn.microsoft.com/en-us/library/de0542zz.aspx

如果你想要一个螺旋锁类型,你可以使用ReaderWriterLockSlim()

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx