C# NET监视器何时进入内核模式?

C# NET监视器何时进入内核模式?,c#,.net,multithreading,.net-4.0,.net-4.5,C#,.net,Multithreading,.net 4.0,.net 4.5,我想编译一个使监视器进入内核模式/使用内核同步对象的所有可能条件的列表 Sync块有一个引用内核对象的字段,因此我推断lock将在某个时候进入内核模式 我发现: 但是它有太多的问题需要回答,唯一有用的信息是OP回答了他自己的问题,简单地说锁将在某个时候进入内核模式。也没有任何链接来支持这个答案 我的问题是不同的-我想知道lock何时会进入内核模式(不是if,也不是why-when) 如果.NET4和4.5与旧版本有什么不同,我更感兴趣 编辑:摘自里克特著作:“同步块包含内核对象的字段、所属线程的

我想编译一个使监视器进入内核模式/使用内核同步对象的所有可能条件的列表

Sync块有一个引用内核对象的字段,因此我推断
lock
将在某个时候进入内核模式

我发现:

但是它有太多的问题需要回答,唯一有用的信息是OP回答了他自己的问题,简单地说
锁将在某个时候进入内核模式。也没有任何链接来支持这个答案

我的问题是不同的-我想知道
lock
何时会进入内核模式(不是if,也不是why-when)

如果.NET4和4.5与旧版本有什么不同,我更感兴趣


编辑:摘自里克特著作:“同步块包含内核对象的字段、所属线程的ID、递归计数和等待线程计数。”

在其spinwait步骤之后


可能存在其他智能,例如跳过单核机器上的spinwait,因为只有在释放线程后才能释放有争议的锁

当锁被严重争用时


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

大多数这类问题都可以通过查看CLR源代码来回答。它现在已经很过时了,它是.NET2.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类进入内核模式。

Andrew我需要在平面视图中完成所有步骤,以查看这是如何回答问题的。你的回答就像——当人们被闪电击中而死亡时——当他们死亡时。@BoppityBop:去给自己弄一架飞机和一条简易机场,然后我们讨论这一点。如果你想要更精确的,那么“5:04:02.008”怎么样?说真的,绝对答案是无用的,而相对答案则各不相同。唯一剩下的就是一个合乎逻辑的答案。上一步完成后,您的问题缺少您想要的要点。你为什么在乎?如果你能提供,我们也许能提供一个更有用的答案。非常感谢。特别是对于SSCLI-我不知道这是公开的。谢谢你的评论,它指向了CLR源代码中的相关部分。我对旋转部分特别感兴趣:通常都说监视器在进入内核之前首先旋转。我感兴趣的是它到底是如何旋转的(迭代次数,…)。我看不到在您描述的代码路径中旋转,但是,我在由AwareLock::TryEnter调用的AwareLock::Conversion中看到旋转逻辑。现在看来,这只适用于使用timeout时的TryEnter,所以我猜在使用c#lock关键字时不使用旋转。我说得对吗?