26

我很困惑。一个或多个如何Task在单个线程上并行运行?我对并行性的理解显然是错误的。

一些 MSDN 我无法理解:

async 和 await 关键字不会导致创建额外的线程。异步方法不需要多线程,因为异步方法不在其自己的线程上运行。该方法在当前同步上下文上运行,并且仅在该方法处于活动状态时才使用线程上的时间。

.. 和:

在开始任务和等待它之间,您可以开始其他任务。附加任务隐式并行运行,但不创建附加线程。

4

1 回答 1

25

它们不是并行运行,而是轮流运行。当正在运行的任务的进度被阻止时,它会存储其状态并将控制权交给就绪的任务。这是协作式多任务处理,而不是真正的并行性。

线程按样本原理运行。但是,我想强调几个关键区别。

首先,仅仅因为async/await不是操作系统线程:

  • 任务不会看到不同的线程 ID
  • 当任务产生时,线程本地存储不会自动进行上下文切换。

其次,行为上的差异:

  • async/await使用协作多任务,Win32 线程使用抢占式。因此,所有阻塞操作都必须使用async/await模型显式地产生控制。因此,您可以通过对未编写为 yield 的函数进行阻塞调用来最终阻塞整个线程及其所有任务。
  • 任务不会在多处理系统上并行执行。由于控制了重入,这使得保持数据结构的一致性变得更加容易。

正如斯蒂芬在评论中指出的那样,如果您使用多线程同步上下文,您可以在多个操作系统线程中同时执行(以及所有复杂性和潜在的竞争条件)。但是 MSDN 的引用是关于单线程上下文案例的。

最后,在其他地方也使用了相同的设计范例,您可以通过研究这些来了解很多关于async/的良好实践的信息:await

  • Win32 Fibers(使用与线程相同的调用方式,但协作)
  • Win32重叠 I/O操作,Linux aio
  • 协程
于 2012-12-21T16:32:57.897 回答