c# lock 关键字是否使用“yielding”、“spin-locking”或混合方法来处理争用?
到目前为止,我对 .net lock 语句的搜索还没有找到答案。如果我找到更多,我会发布。到目前为止,我所能找到的只是什么时候应该使用自旋锁...... Mecki 给出了一个措辞优美的接受答案。
但是我正在寻找一些关于 .net/c# 的明确答案或文档(如果有人有的话)。
c# lock 关键字是否使用“yielding”、“spin-locking”或混合方法来处理争用?
到目前为止,我对 .net lock 语句的搜索还没有找到答案。如果我找到更多,我会发布。到目前为止,我所能找到的只是什么时候应该使用自旋锁...... Mecki 给出了一个措辞优美的接受答案。
但是我正在寻找一些关于 .net/c# 的明确答案或文档(如果有人有的话)。
以下代码:
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 编译器,不同硬件的算法可能不同)。
这是 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