.NET线程是轻量级用户模式线程还是内核模式操作系统线程?
另外,保留SQL Server,.NET线程和操作系统线程之间是否存在一对一的对应关系?
我也很感兴趣,因为Thread
类有一对名为BeginThreadAffinity
和EndThreadAffinity
的对称方法,其文档巧妙地暗示.NET线程是真实操作系统的轻量级抽象线程。
另外,我刚才读到一些堆栈溢出线程本身,微软试图在CLR中维护这种分离,就像SQL Server一样。我记得有一些项目正在使用Fiber API来实现这个目的,但我不能说我理解了所读的所有细节。
我想要一些关于这个主题的更详细的文献,例如.NET线程的内部结构与Windows创建的线程的内部结构相比。虽然有很多关于Windows创建的线程结构的信息,但Jeffrey Richter的高级Windows编程书是其中一个来源,例如,我找不到任何专门针对内部的文献.NET线程的结构。
有人可能会争辩说,这些信息可以在.NET源代码中找到,现在可以公开获得,或者使用反汇编程序(如Reflector或IL Spy),但是我没有看到任何代表线程控制块的信息(TCB) )和程序计数器(PC)和堆栈指针(SP)或线程的等待队列,或者线程当前是Thread
类中成员的队列列表。
我在哪里可以读到这个?文档中是否提到了它的任何内容?我已经阅读了所有these pages from the MSDN但他们似乎没有提到它。
答案 0 :(得分:14)
.NET的线程确实是抽象,但你基本上可以认为它们与操作系统线程几乎相同。有一些关键的差异,特别是在垃圾收集方面,但绝大多数程序员(阅读:不太可能启动WinDBG的程序员)没有功能差异。
答案 1 :(得分:0)
在决定如何进行并发之前,了解有关预期性能和预期并发的性质很重要。例如,.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个任务,平均启动时间为885ms
所有512个OS线程均以59毫秒的平均开始时间运行完毕。
无论谁说什么,在.NET中从调用API到启动执行单元以及执行实际单元的路径要长得多。