并发!=并行
首先,假如我们有一段CPU密集型任务,我们创建2000个gorountine是否真的可以将性能提升2000倍?答案是肯定不能,因为我们只是做到了2000次的并发(concurrency),并没有真正做到并行(parallelism)。
并发指的是我们的程序执行逻辑,传统单线程应用的程序逻辑是顺序执行的,在任何时刻,程序只能处理统一个逻辑。而并发指的是,我们同时执行多个独立的逻辑程序,若干个程序逻辑在执行的时候是同时进行的。实际上,不论我们并发多少个逻辑程序,若我们仅仅将其运行在一个单核单线程的CPU上,都不能让你的程序性能有所提升,因为最终所有任务都要排队等待CPU资源(时间片)。
而并行才能让我们的程序真正的同时处理多个任务,但并行并不是编程语言带给我们的特性,他需要硬件支持。面说到单核CPU所有资源都要等待同一个CPU的资源,那么其实我们只要将CPU增多就能真正的让我们实现并行。我们可以使用多核CPU或者多台服务器组成服务集群,才能实现正常的并行,能够并行处理的任务数量也就是我们的CPU数量。
CPU密集型 & I/O密集型
那么是不是说我们在单核CPU的机器上使用编程语言所提供的多线程就没有意义了呢?
如果说我们的程序属于CPU密集型,使用并发编程,可能确实无法提升我们的程序性能,甚至可能因为大量计算资源花在了创建线程本身,导致程序性能进一步下降。
但不同的是,如果说我们的程序属于IO密集型,当你在进行程序压测的过程中可能发现CPU占用率很低,但性能却到了瓶颈,原因是程序将大量的时间花在了等待IO的过程中,如果我们可以在等待IO的时候继续执行其他的程序逻辑即可提高CPU利用率,从而提高我们的程序性能,这时并发编程的好处就出来了,例如Python因为GIL的存在实际上并不能实现真正的并行,但他的多线程依旧在IO密集型的程序中依旧有种很重要的意义。