关于.net:什么是C#线程类型?

What's C# threading type?

在三种类型的线程(内核级,用户级和混合型)之间,C#(或更常见的.NET)使用哪种类型的线程?


核心线(1:1)

术语"内核线程"可以用来指代完全在内核空间中运行的实际线程,也可以指代由内核调度的用户空间线程。术语"内核支持"线程是指后者,它们在用户空间中运行,但由内核提供便利,这通常意味着内核会对其进行调度。

内核线程具有特权,可以访问用户模式线程之外的内容。看看Wikipedia上的" Ring(计算机安全性)"。在Windows上,用户模式对应于Ring 3,而内核模式对应于Ring 0。

用户级别线程(N:1)

"用户级线程"通常是指用户空间可见的线程。也就是说,您在调用线程标准的"创建线程"函数时所创建的内容。通常,术语"用户级线程"用于表示由应用程序代码创建的线程,而与系统如何实现无关。它可能是纯用户空间线程,几乎没有内核支持,也可能是内核调度的线程。

混合线程(M:N)[WikiPedia]

M:N将M个应用程序线程映射到N个内核实体或"虚拟处理器"上。这是内核级(" 1:1")和用户级(" N:1")线程之间的折衷方案。通常," M:N"线程系统的实现比内核或用户线程更复杂,因为需要同时更改内核和用户空间代码。在M:N实现中,线程库负责在可用的可调度实体上调度用户线程。这使得线程的上下文切换非常快,因为它避免了系统调用。

.Net线程是使用Win32 API并将其包装为一个不错的框架的用户级线程!

可以找到更多详细信息:

  • 线程(计算)
  • 内核线程与内核支持的线程与用户级线程
  • 用户线程和内核线程
  • 线程是内核对象吗?


它不取决于C#本身,而取决于运行时-CLR。

.Net可以考虑支持两种模式:

  • 仅用户土地调度(或Windows UMS)。在这种模式下,一个用户登陆线程可以执行上下文切换到另一个用户模式线程,而无需实际更改内核线程。这种模式增加了很多编码开销,但是在内核级上下文切换中节省了宝贵的10-20微秒。
  • 混合模型(迄今为止最受欢迎)。在此模型中,托管代码要求访问内核,例如读取文件。通过一组API,代码执行过程从用户域.NET调用进入Windows API,再进入内核,驱动程序,HAL层和物理驱动器。然后通过调用堆栈取回数据。如果上下文切换是由线程调度程序启动的,那么用户线程和内核线程将被更改。

不允许直接内核模式线程化,因为托管代码不具有在内核模式下运行的特权。它只能调用Windows API,后者又会切换到内核模式。

如果使用ThreadTaskThreadPool-CLR使用混合模型。使用混合模型是因为CLR创建了托管对象来表示该类。任何托管代码都在用户域中运行。但是,每个未创建为纤维的线程(请参见下文)(无论是否在线程池中)都具有底层内核数据结构。内核数据结构用于保存线程的内核状态-内核线程ID,创建和退出时间,进程ID,启动线程地址,安全访问令牌,数十个计时器,CPU寄存器,内核堆栈等。所有这些都需要在更新期间上下文切换,但是我们只需要大约10-20 * 10 ^ -6秒的时间。

如果在Ums的C ++调用集周围使用托管包装(例如CreateUmsThreadContext,UmsThreadYield和许多其他调用),则CLR尝试使用UMS模式。但这仅针对您专门手动操作的几个线程。您的应用程序仍将使用混合模型,在用户模式下彼此之间将仅手动产生一些手动选择的线程(纤维)。但是即使在这种模式下,OS Task Scheduler有时也会启动内核线程切换,因此您永远不会卡死执行UMS调度的线程。

为了完整性,

  • 内核模式调度是一种非常低级的机制,只能从内核访问。这意味着,只有开发操作系统内部组件或某种驱动程序,才能使用它。这样的调度很难使用,有任何错误,整个操作系统被冻结/卡住/崩溃/蓝屏死机或转移到任何其他不可预测的状态。内核级线程需要大量的开发和测试工作。例如,Windows任务计划程序或内存管理服务使用内核模式计划。您能想象一下编写这些组件要花费多少时间,以便它们在高度多线程的环境中稳定吗?