.NET 线程与操作系统线程不同吗?

Are .NET threads different from operating system threads?

  1. .NET 线程是轻量级用户模式线程还是内核模式操作系统线程?

  2. 另外,备用SQL服务器,.NET线程和操作系统线程之间是否存在一对一的对应关系?

我也很感兴趣,因为 Thread class 有一对名为 BeginThreadAffinity and EndThreadAffinity 的对称方法,其文档巧妙地表明 .NET 线程是对真实操作系统的轻量级抽象线程。

此外,我不久前在一些堆栈溢出线程本身上读到,Microsoft 试图在 CLR 中保持这种分离,就像 SQL 服务器所做的那样。我记得有一些正在进行的项目正在为此目的使用 Fiber API,但我不能说我理解了所读内容的所有细节。

我想要一些关于此主题的更详细的文献,例如 .NET 线程的内部结构与 Windows 创建的线程的内部结构。虽然有大量关于 Windows 创建的线程结构的可用信息,但 Jeffrey Richter 的 Advanced Windows Programming 一书就是其中的来源之一,例如,我找不到任何专门介绍 .NET 线程内部结构的文献。

有人可能会争辩说,此信息可在 .NET 源代码(现已公开)或使用反汇编器(如 Reflector 或 IL Spy)中获得,但我看不到任何表示线程控制块的内容(TCB) 和程序计数器 (PC) 和堆栈指针 (SP) 或线程的等待队列,或线程当前所属的队列列表 Thread class.

我在哪里可以读到这方面的信息?文档中是否提到了其中的任何一个?我已经阅读了全部 these pages from the MSDN 但他们似乎没有提到它。

.NET 的线程确实是抽象的,但你基本上可以认为它们与 OS 线程几乎相同。存在一些关键差异,尤其是在垃圾收集方面,但对于绝大多数程序员(阅读:不太可能启动 WinDBG 的程序员)而言,没有功能差异。

For more detail, read this

在决定如何进行并发之前,了解预期性能和预期并发的性质很重要。例如,.NET 是一个虚拟机,因此并发是模拟的。这意味着启动执行的开销比直接 OS 线程更多。

如果您的应用程序打算按需实现大量并发,则 .NET 任务或线程(甚至 ThreadPool)的创建和开始执行速度会很慢。在这种情况下,您可能会受益于 Windows OS 线程。但是,您会希望使用非托管线程池(除非您像我一样喜欢编写自己的线程池)。

如果按需启动不确定数量的线程的性能不是设计目标,那么您应该考虑 .NET 并发性。原因是它更容易编程,并且您可以利用影响编程语言内置的并发性的关键字。

为了正确看待这个问题,我编写了一个测试应用程序,在不同的并发执行单元中测试算法 运行。我 运行 在我自己的非托管线程池、.NET Tasks、.NET Threads 和 .NET ThreadPool 下进行测试。

将并发设置为 512,这意味着将尽可能快地调用 512 个并发执行单元,我发现任何 .NET 在开始时都非常慢。我 运行 在几个系统上进行了测试,从具有 16gb RAM 的 i5 4 核台式机到 Windows Server 2012 R2,结果是相同的。

我捕获了已完成的并发执行单元数、每个单元启动所需的时间以及 CPU 核心利用率。每次测试的持续时间为 30 秒。

所有测试的结果都是均衡的 CPU 核心利用率(与某些人的看法相反)。然而,任何 .NET 都会输掉比赛。 30 秒后...

.NET 任务和线程 (ThreadPool) 完成了 34 个任务,平均启动时间为 885 毫秒

全部 512 OS 个线程 运行 完成,平均启动时间为 59 毫秒。

不管别人怎么说,从调用 API 开始执行单元到实际执行单元的路径在 .NET 中要长得多。