6

c# lock 关键字是否使用“yielding”、“spin-locking”或混合方法来处理争用?

到目前为止,我对 .net lock 语句的搜索还没有找到答案。如果我找到更多,我会发布。到目前为止,我所能找到的只是什么时候应该使用自旋锁...... Mecki 给出了一个措辞优美的接受答案。

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

4

3 回答 3

10

以下代码:

lock (_syncRoot)
{
    // Do stuff
}

由编译器翻译为:

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

这是幼稚(和旧)的实现,实际上使用 .NET 4.0 的实现或多或少是这样的(请参阅Eric 的博客以获取完整参考):

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

已编辑

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

我正在阅读并发 Windows 编程(由 Joe Duffy 撰写)时,有一段确实引起了我的注意,我的第一个答案是“不,它不使用旋转,因为在一般情况下性能可能不好”。正确答案是“是的,.NETMonitor使用旋转”。.NETMonitor和 Windows 关键部分都执行短暂的旋转,然后再回到对内核对象的真正等待。这种算法被称为“两阶段锁定协议”,它是合适的,因为上下文切换和内核转换非常广泛,在多处理器机器上旋转可以避免这两者。

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

于 2012-07-06T12:12:43.847 回答
1
lock (obj)
{
}

只是Monitor的语法糖。输入尝试...终于。

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

现在稍微好一点了(感谢 Mark 和 Adriano 让我了解最新情况)。

bool locked = false;  
try  
{  
    Monitor.Enter(_syncRoot, ref locked);  
}  
finally  
{  
    if (locked)  
        Monitor.Exit(_syncRoot);  
} 
于 2012-07-06T12:11:37.647 回答
0

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

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

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

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

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

于 2012-07-06T12:15:23.480 回答