有一个Channel 9 Video试图解释线程和任务之间的区别。我通常喜欢9频道的视频,因为他们的技术准确性不错,但从我的理解来看,这个视频的一些关键声明是错误的。任务与线程的Channel 9解释是否正确?
下面是语句:
- @〜1:48至〜2:30:线程是在存储器和时间昂贵。每个线程获得1 MB的用户模式堆栈。
- @〜2:30到2:37:创建线程也需要时间。分配数据结构并初始化它们的时间。
- @〜2:38到2:45:上下文切换也需要时间。
- @〜2:58至3:23和3:48至:任务使用多核系统[...]因此,当您计算时,您正在使用多个核心。
- @〜5:02至5:30:线程运行在单个内核上,上下文切换发生很多。
- @〜5:40至5:51:线程有不同的执行方式。它们在多个内核上执行。如你在图中看到的那样,线程已经开销了。
这里是我的想法,我想证实或证伪:
调用堆栈的数量是可配置的。这样,线程限制不是~1300,而是32位进程的最高限制为12000。那些谁拥有可用的Sysinternals TestLimit的副本可以试试:
D:\>testlimit -t -n 64 Testlimit v5.04 - test Windows limits By Mark Russinovich - www.sysinternals.com Creating threads with 64 KB stacks... Created 12500 threads. Lasterror: 8
堆栈大小也被暴露在Thread Constructor for .NET
任务依靠线程作为基础。这些线程取自线程池,但是线程池的线程需要在可以使用之前创建。 AFAIK,Mark Russinovich在Windows Internals书中也解释说,内核结构(
_ETHREAD
)保存在内存中以供重用。这最大限度地减少了分配的开销并将其减少到初始化。我没有找到我一直在寻找的确切地点,但在Windows内部6,第1部分它说417页:
[...]执行线程对象可能或不可能被释放。
由于任务依赖线程作为技术实现,因此在任何情况下都会发生上下文切换。
如果我有2个线程,它们也可以在不同的处理器上执行。恕我直言,这是它的全部想法。
这位演讲者在讨论单核心系统上的线程问题。恕我直言,任务在这种情况下也几乎没有任何好处。见4.)
见4.和5。)
该幻灯片可能是正确的,但并未显示实际原因。该幻灯片丢失导致上下文切换的〜15ms时间片。如果线程需要等待结果,则只能使用任务来减少开销。
在这种情况下,幻灯片的下半部分也是不正确的,因为工作1的第一部分似乎是阻塞的,在这种情况下,工作2只能执行。当工作2完成时,可以完成继续工作1的条件。只有在时间片内发生所有事情,任务才有好处。
在任何情况下,上下文切换也将随任务一起发生,迟早。
我曾试图确认我有这些问题的帮助理解上SO
上面似乎是7点个人的问题。我问他们都在同一个地方,因为
- 所有的根源在于一个视频
- 一些问题互相依赖
- 它来查找信息在一个地方比继SO规则的恕我直言更重要一次提出一个问题。
我根本不知道.net,但听起来好像'Task'是你提交给_thread pool_的东西,是吗?如果是这样,线程池的重点是_re-use_ threads。正如你所说,线程是创建和销毁昂贵的。一个不断需要在后台执行小作业的程序可以为每个线程启动一个新线程,并在作业完成时销毁该线程,或者可以使用一些长寿命的后台线程,并用“任务'对象通过一个队列。后一种策略效率更高。 –
@jameslarge任务*可以*运行在线程池(例如task.run执行此IIRC),但这只是他们行为的一个方面。 Task.FromResult不使用线程池,但它仍然是一项任务。此外,可以在不使用任务库/ API的情况下使用线程池。使用线程池来处理任务是一种常见而有效的策略,这是正确的。 – NPSF3000
“任务可以使用.Net中的线程池执行更为正确。” - 我同意。如果它不使用线程池,则需要从头创建一个新线程,它具有与通常线程相同的性能。 –