【问题标题】:When exactly does .NET Monitor go to kernel-mode?.NET Monitor 究竟何时进入内核模式?
【发布时间】:2013-02-17 15:04:39
【问题描述】:

我想编制一份清单,列出使 Monitor 进入内核模式或使用内核同步对象的所有可能条件。

同步块有一个引用内核对象的字段。因此我推断lock有时会进入内核模式。

我发现了这个:Lock (Monitor) internal implementation in .NET

但是它有太多问题需要回答,唯一有用的信息是 OP 通过简单地说明lock 有时会进入内核模式来回答他自己的问题。也没有任何链接可以支持该答案。

lock 究竟何时会进入内核模式(不是如果,也不是为什么 - 何时)?

如果与旧版本有任何区别,我更感兴趣了解 .NET 4 和 4.5。

来自 Richter 的书:“同步块包含内核对象的字段、拥有线程的 ID、递归计数和等待线程计数。”

【问题讨论】:

    标签: c# .net multithreading .net-4.0 .net-4.5


    【解决方案1】:

    大多数此类问题都可以通过查看SSCLI20 distribution 提供的 CLR 源代码来回答。它现在已经过时了。它是 .NET 2.0 的经典版本,但很多核心 CLR 功能并没有太大变化。

    您要查看的源代码文件是 clr/src/vm/syncblk.cpp。三个类在这里发挥作用。 AwareLock 是负责获取锁的低级锁实现,SyncBlock 是实现等待进入锁的线程队列的类,CLREvent 是操作系统同步对象的包装器,您就是询问。

    这是 C++ 代码,抽象级别相当高。此代码与垃圾收集器进行大量交互,并且包含大量测试代码。因此,我将简要介绍该过程。

    SyncBlock 具有存储 AwareLock 实例的 m_Monitor 成员。 SyncBlock::Enter() 直接调用 AwareLock::Enter()。它首先尝试尽可能便宜地获取锁。首先检查线程是否已经拥有锁,如果是这样,就增加锁计数。接下来使用 FastInterlockCompareExchange(),这是一个与 Interlocked.CompareExchange() 非常相似的内部函数。如果锁没有被争用,那么这会很快成功并且 Monitor.Enter() 返回。如果不是,则另一个线程已经拥有该锁,并使用 AwareLock::EnterEpilog。需要让操作系统的线程调度程序参与进来,因此使用 CLREvent。如果需要,它会动态创建,并调用其 WaitOne() 方法。这将涉及内核转换。

    所以足以回答您的问题:Monitor 类在锁被争用并且线程必须等待时进入内核模式。

    【讨论】:

    • 非常感谢。特别是对于 SSCLI - 我不知道这是公开的。
    • 感谢评论指出我在 CLR 源代码中的相关部分。我对旋转部分特别感兴趣:通常在进入内核之前第一次旋转时声称 Monitor。我很感兴趣它是如何旋转的(迭代次数,...)。我看不到您描述的代码路径中的旋转,但是,我在由 AwareLock::TryEnter 调用的 AwareLock::Contention 中看到了旋转逻辑。现在看来,这只适用于使用超时时的 TryEnter,所以我猜想在使用 c# lock 关键字时不使用旋转。我说的对吗?
    【解决方案2】:

    当锁被严重争用时。

    如果锁被轻微争用,有一个快速的 CPU 自旋锁来等待锁再次被释放,但如果这等待时间不足以释放锁,线程将阻塞等待互斥锁,这涉及到内核模式调用以挂起线程和其他此类管理。

    【讨论】:

      【解决方案3】:

      在其 spinwait 步骤之后,可能存在额外的智能,例如在单核机器上跳过 spinwait,因为竞争锁只能在释放线程后释放。

      【讨论】:

      • 安德鲁 我需要在平面视图中查看所有步骤,看看这如何回答问题。你的回答就像 - 当人们被闪电击中时死亡 - 当他们死亡时。
      • @BoppityBop:去给自己买一架飞机和一个简易机场,然后我们讨论这一点
      • 是的。如果你想要更精确的东西,“at 5:04:02.008”怎么样?说真的,绝对答案是没有用的,相对答案会有所不同。唯一剩下的就是一个合乎逻辑的答案。上一步完成后,您的问题缺少您所追求的点。你为什么在乎?如果您提供了,我们也许可以提供更有用的答案。
      猜你喜欢
      • 2013-12-01
      • 1970-01-01
      • 2011-04-20
      • 2020-08-19
      • 2023-01-24
      • 2011-05-09
      • 1970-01-01
      • 2017-12-11
      相关资源
      最近更新 更多