进程是系统进行资源分配和保护的基本单位,线程是处理器调度和分派的基本单位
拿Java程序来说,启动后,每一个JVM其实就是一个进程。所有的资源分配都是基于JVM进程来的。而在这个JVM进程中,又可以创建出很多线程,多个线程之间共享JVM资源,并且多个线程可以并发执行。
进程具有一个独立的执行环境。 进程是程序在计算机上的一次执行活动 。通常情况下,进程拥有一个完整的、私有的基本运行资源集合。特别地,每个进程都有自己的内存空间。
进程往往被看作是程序或应用的代名词,然而,用户看到的一个单独的应用程序实际上可能是一组相互协作的进程集合
线程有时也被称为轻量级的进程。进程和线程都提供了一个执行环境,但创建一个新的线程比创建一个新的进程需要的资源要少。线程是在进程中存在的,每个进程最少有一个线程。线程又如下特点:
所谓的协程,是英语翻译过来的(Coroutine),也叫纤程。通过Coroutine来理解,是协作的程序。它其实是不能和进程,线程相提并论的,因为协程是用户态的东西,不会被OS感知到的。但是因为GoLang的大火,大家总是把他们放到一起来比较,所以在这里也一起讲了。
对于多次IO操作来说,我们可以用多线程来完成,但是多线程会引起资源竞争,导致CPU算力的浪费。为了避免这种情况,我们也可以用异步的方式,但是异步的方式会引起callback hell,严重影响了代码的可读性。
所以就需要协程,不让OS通过竞争的方式决定调用哪些线程,而是由用户自己决定如何去执行逻辑。它可以让我们用逻辑流的顺序去写控制流,而且还不会导致操作系统级的线程阻塞。因为协程是由应用程序决定的,所以任务切换的上下文也会交给了用户态来保存。目前GO和Ruby等编程语言都实现了协程,Java也在19的时候引入了协程。可以参考:
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。
而在多个进程之间切换的时候,需要进行上下文切换。但是上下文切换势必会耗费一些资源。于是人们考虑,能不能在一个进程中增加一些“子任务”,这样减少上下文切换的成本。比如我们使用Word的时候,它可以同时进行打字、拼写检查、字数统计等,这些子任务之间共用同一个进程资源,但是他们之间的切换不需要进行上下文切换。
所以,在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。这就是为什么有了进程,又有线程。
但是,多个线程的切换还是需要时间的,而且多线程也会竞争CPU资源引起不必要的资源浪费,更不要说加锁阻塞了。所以,有没有可能不做切换,充分压榨CPU的资源呢?这就诞生了协程。协程可以将用户自己决定什么时候切换,而不是让操作系统去做抢占式调度,这样就大大节约了资源。