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

标签 c# .net multithreading locking

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

到目前为止,我对 .net lock 语句的搜索还没有找到答案。 如果我找到更多,我会发布。 到目前为止我能找到的是 When should one use a spinlock ... Mecki 接受了一个措辞优美的答案。

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

最佳答案

以下代码:

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);
}

已编辑

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

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

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

关于c# - lock语句使用什么类型的锁定机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11361915/

相关文章:

c# - 带有 Entity Framework 的 MVC 中的列表框控件

C# 到 C++ 多线程,会出现什么问题?

c# - 当 c# .net using block 失败时会发生什么?

multithreading - 如何将 Tokio 线程池限制为一定数量的 native 线程?

c# - 在 GridView 中单击“删除”按钮时显示文本

c# - 使用或不使用 "this"关键字来引用同一类中的方法有区别吗?

.net - 无论如何可以轻松地在 Visual Studio 2010 中移动整个方法 block

c# - 在运行时更新 app.config system.net 设置

multithreading - 尝试两次接收值时出现死锁

c# - 我可以告诉 .NET GC 不理会某些线程吗?