.NET Monitor 何时进入内核模式? [英] When exactly .NET Monitor goes to kernel-mode?

查看:27
本文介绍了.NET Monitor 何时进入内核模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to compile a list of all possible conditions making Monitor go to kernel-mode / use kernel sync object.

同步块有一个字段来引用内核对象,因此我推断 lock 会在某个时候进入内核模式.

Sync block has a field to reference kernel object hence I deducted that lock will go to kernel-mode sometime.

我发现了这个:.NET 中的锁定(监控)内部实现

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

but it has too many questions to be answered and the only useful information is that the OP answered his own question by simply stating that the lock will go to the kernel-mode sometime. Also there is no links to anything to support that answer.

我的问题是不同的 - 我想知道 lock 什么时候会进入内核模式(不是如果,不是为什么 - 什么时候).

My question is different - I want to know when exactly lock will go to kernel-mode (not if and not why - when).

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

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

推荐答案

大多数此类问题都可以通过查看通过 SSCLI20 分发.它现在已经很过时了,它是 .NET 2.0 版本,但许多核心 CLR 功能没有太大变化.

Most of these kind of questions can be answered by looking at the CLR source code as available through the SSCLI20 distribution. It is getting pretty dated by now, it is .NET 2.0 vintage, but a lot of the core CLR features haven't changed much.

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

The source code file you want to look at is clr/src/vm/syncblk.cpp. Three classes play a role here, AwareLock is the low-level lock implementation that takes care of acquiring the lock, SyncBlock is the class that implements the queue of threads that are waiting to enter a lock, CLREvent is the wrapper for the operating system synchronization object, the one you are asking about.

这是 C++ 代码,抽象级别相当高,这段代码与垃圾收集器交互频繁,并且包含大量测试代码.那么我就简单介绍一下这个过程.

This is C++ code and the level of abstraction is quite high, this code heavily interacts with the garbage collector and there's a lot of testing code included. So I'll give a brief description of the process.

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

SyncBlock has the m_Monitor member that stores the AwareLock instance. SyncBlock::Enter() directly calls AwareLock::Enter(). It first tries to acquire the lock as cheaply as possible. First checking if the thread already owns the lock and just incrementing the lock count if that's the case. Next using FastInterlockCompareExchange(), an internal function that's very similar to Interlocked.CompareExchange(). If the lock is not contended then this succeeds very quickly and Monitor.Enter() returns. If not then another thread already owns the lock, AwareLock::EnterEpilog is used. There's a need to get the operating system's thread scheduler involved so a CLREvent is used. It is dynamically created if necessary and its WaitOne() method is called. Which will involve a kernel transition.

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

So enough there to answer your question: the Monitor class enters kernel mode when the lock is contended and the thread has to wait.

这篇关于.NET Monitor 何时进入内核模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆