我已经阅读了一些有关异步/等待vs线程池vs线程的知识,我不得不承认,我不清楚细节。我有一个特定的问题,我认为,但是我不能肯定地说。
我也知道关于SO和其他地方的许多问题,这些问题正在讨论和解释中。我在这里已经读到了一些关于SO的文章,但是我没有找到明确的答案,或者至少没有我想要的清晰。
我收集了什么
但是,一位同事说了这样的话:
所以,我要问的是:
请注意,我并不是从服务器的角度讨论客户端的事情。
如果对这个问题没有确切的答案,请提前抱歉,我已经看过=)
答案 0 :(得分:5)
真正的问题不是“线程池与async
/ await
”,而是同步I / O与异步I / O。 [1]
在Windows上,线程是相对昂贵的对象-线程具有大量与之相关的操作系统记账,更不用说1 MB的预分配堆栈空间。这对系统甚至支持多少线程设置了一个较低的上限,即使您没有达到该上限,在所有这些线程之间进行上下文切换也不便宜。 “ 32,000个线程”的限制是一个严格的理论限制,并且对您可以拥有多少个线程并且仍然保持响应状态非常乐观! [2]
输入异步I / O,该异步I / O经过优化以仅使用所需的多个线程(通常是系统中物理处理器内核数量的保守倍数),理想情况下甚至从不创建超出初始批处理的新线程。这些线程专用于通过从队列(称为完成端口)中删除它们来处理已完成的I / O操作。在进行异步操作时,根本没有线程专用于此,甚至没有作为等待列表中的项使用(Stephen Cleary对此有一个不错的blog post对此进行了详细说明)。不需要太多的想象力就可以考虑哪种方法更有效:
事实证明,后者的规模要比前者好得多;即使在使用线程池减少创建新线程的情况下,天真服务器代码中常见的“每个请求线程”模型也会很快显示其局限性。请注意,这早在async
/ await
成为一个问题之前就已经存在,Windows所采用的解决方案也是如此。 async
/ await
只是一种编写代码以使用现有机制的新方法。
您是否可能一次注意到只有几个请求而有所不同?不会。但是由于async
/ await
本质上允许您编写看起来是同步的代码,但具有“免费”异步I / O的可伸缩性,所以为什么不选择用它来支持排队到线程池的同步I / O?
[1]证明斯蒂芬·克拉里(Stephen Cleary)几年前wrote most of what's in this answer。我也建议您阅读。
[2]这是Mark Russinovich的older post,他实际上试图从系统中挤出尽可能多的线程-只是为了娱乐和牟利。在所有资源用尽之前,他“只能”在64位计算机上达到55K,这是通过调整默认堆栈大小,而不进行任何实际有用的工作。在现代系统上,您可能会得到更多,但真正的问题不应该是“我可以拥有多少个线程”-如果是,那么您做错了。