我使用coroutines很长时间,但我仍然不完全理解,为什么我需要选择多线程协同而不是单线程coroutines。
我可以清楚地看到,当多线程协同器的数量小于或等于物理线程计数时,使用它们的好处。但是如果我们有比物理线程更多的任务,为什么我们不选择只使用一个协同线程呢?
我将澄清最后一个问题:为什么10个协同线程比只有一个有多个协同线程的线程更好?
发布于 2022-01-06 10:34:49
协同线是计算的单位(如任务)。它们被分派到实际线程的方式与您有多少个协同线是正交的。您可以使用单线程调度程序或多线程调度程序,根据这一点,您的协同任务将被不同的调度。
多线程协同并不意味着每个协同线有一个线程。您可以在8个线程上分派100个协同器。
但是如果我们有比物理线程更多的任务,为什么我们不选择只使用一个协同线程呢?
这个问题有多个部分。
首先,如果您有比逻辑核心更多的任务,那么仍然可以将所有这些任务分派到正确数量的线程上。你不需要完全放弃多线程。实际上,这正是Dispatchers.Default
所要做的:将任意数量的协同任务分配到有限数量的线程上,这与您拥有的硬件线程(逻辑核)数量相等。重点是尽可能多地利用所有硬件,而不浪费theads (因此也就是内存)。
第二,不是每个任务都是CPU绑定的.一些I/O操作阻塞线程(网络调用、磁盘读/写等)。当线程在I/O上被阻塞时,它不使用CPU。如果您有8个逻辑核心,只使用8个线程进行I/O将不是最佳的,因为当一些线程被阻塞时,CPU无法运行其他任务。有了更多的线程,它可以(以一些内存为代价)。这就是Dispatchers.IO
的要点,它可以根据需要创建更多的线程,并且可以超过逻辑核的数量(在合理的限制范围内)。
为什么10个协同线程比只有一个有多个协同线程更好?
假设您有100个协同任务要调度。
只使用一个线程来运行这些协同工作意味着,最多只有一个核心在给定的时间内完成工作,所以没有任何事情并行发生。这意味着所有其他核心都是空闲的,这是次优的。更糟糕的是,coroutine执行的任何I/O操作都会阻塞这个唯一的线程,并阻止CPU在等待I/O时执行任何操作。
使用10个线程,如果硬件足够,就可以同时执行10个协同器,速度可以快10倍(如果您的coroutine没有相互依赖关系)。
如果您的协同机制是CPU绑定的,那么使用100个线程就不会有多大益处,但是如果您有一堆I/O任务(正如我们所看到的),则可能会很有用。也就是说,使用的线程越多,占用的内存就越多。因此,即使有大量的I/O操作,您也必须在吞吐量和内存之间找到平衡,您不希望产生数百万个线程。
总之,使用多线程仍然有着同样的优势,不管有没有协同:它允许尽可能多地利用您的硬件资源。使用协同机制只是定义任务、将它们分派到线程、表示依赖关系、避免不必要地阻塞线程等方面的一种更简单的方法。
https://stackoverflow.com/questions/70605277
复制相似问题