【发布时间】:2013-06-14 14:35:11
【问题描述】:
我无意中听到一位同事说任务基本上是一个轻量级线程。来自 C++ 背景(线程是最轻量的处理单元),这对我来说似乎违反直觉。
任务不是和线程一样重吗?
【问题讨论】:
标签: multithreading c#-4.0
我无意中听到一位同事说任务基本上是一个轻量级线程。来自 C++ 背景(线程是最轻量的处理单元),这对我来说似乎违反直觉。
任务不是和线程一样重吗?
【问题讨论】:
标签: multithreading c#-4.0
您需要将工作单元(任务)与用于托管/执行它们的底层进程区分开来。任务甚至不需要在其他线程上运行。例如,可以在单线程应用程序中执行任务,该应用程序会定期将控制权交给任务池。
即使Task在不同的线程上执行,Task和Thread之间通常也不是一对一的关系。线程作为池的一部分被预先分配,然后任务被安排在可用的这些线程上运行。创建新任务不需要创建线程的开销,它只需要任务队列中的 enque 成本。
这使得任务本质上更具可扩展性。在我的应用程序的整个生命周期中,我可以有数百万个任务,但实际上只能使用一些恒定数量的线程。
【讨论】:
Task 独有的。较旧的 ThreadPool 类提供与 IO 控制端口相同的可扩展性,或者仅实现具有固定数量消费者 Threads 的生产者/消费者队列。
通常,“线程”意味着强制并发。启动线程需要为其分配堆栈和内部 OS 数据结构。相比之下,“任务”通常指的是并发性是可选的工作,因此并行框架(例如 OpenMP、Cilk Plus、TBB、PPL)可以使用相同的线程来执行许多任务,通过序列化任务,并仅在必要时将可选并行性转换为真正的并行性以保持机器繁忙。
【讨论】:
Thread 对象的成本与内核数无关,甚至与托管线程映射到的内核线程数无关。成本是 1) 每个 Thread 对象分配大约 1 MB 内存,以及 2) 当线程多于内核时,上下文切换的 CPU 成本。 Task 或 ThreadPool 提供的节省是您的应用程序可以创建 1000 个 Task 对象,而 .NET 可能只使用 20 个 Thread 对象来处理它们。
Thread 对象,而好的选择是创建 N 个Task 对象,在幕后将使用少于 N 个Thread 对象。
你是对的 - 一切都在幕后的线程上运行。
人们之所以说Task 比Thread 更轻量级的原因是,Microsoft 花了很多心思让Tasks 有效利用Threads,而且实现可能要轻得多重量比普通开发人员使用Thread 类自己想出的重量。
编辑
更明确的解释是Task 对象比Thread 对象更轻,虽然每个Task 最终都在Thread 上运行,但同时创建N 个Task 对象会导致小于N 个并发 Thread 正在使用的对象,对于大 N。
【讨论】: