【NOTE】进程-线程-协程 关系与区别

在平时总会听到「进程」、「线程」,甚至最近由于Golang的火热我还听到了「协程」。但是平时我对这三个概念并不能很好的理解,甚至不知它们之间的区别和联系。所以专门找了时间了解了一下它们。本文仅为个人笔记,如有错误或者侵权行为请及时在下方评论里指出!感谢。

进程

一个进程好比是一个程序,它是 资源分配的最小单位 。同一时刻执行的进程数不会超过核心数。不过如果问单核CPU能否运行多进程?答案又是肯定的。单核CPU也可以运行多进程,只不过不是同时的,而是极快地在进程间来回切换实现的多进程。举个简单的例子,就算是十年前的单核CPU的电脑,也可以聊QQ的同时看视频。

电脑中有许多进程需要处于「同时」开启的状态,而利用CPU在进程间的快速切换,可以实现「同时」运行多个程序。而进程切换则意味着需要保留进程切换前的状态,以备切换回去的时候能够继续接着工作。所以进程拥有自己的地址空间,全局变量,文件描述符,各种硬件等等资源。操作系统通过调度CPU去执行进程的记录、回复、切换等等。

线程

如果说进程和进程之间相当于程序与程序之间的关系,那么线程与线程之间就相当于程序内的任务和任务之间的关系。所以线程是依赖于进程的,也称为 「微进程」 。它是 程序执行过程中的最小单元

一个程序内包含了多种任务。打个比方,用播放器看视频的时候,视频输出的画面和声音可以认为是两种任务。当你拖动进度条的时候又触发了另外一种任务。拖动进度条会导致画面和声音都发生变化,如果进程里没有线程的话,那么可能发生的情况就是:

拖动进度条->画面更新->声音更新。你会明显感到画面和声音和进度条不同步。

但是加上了线程之后,线程能够共享进程的大部分资源,并参与CPU的调度。意味着它能够在进程间进行切换,实现「并发」,从而反馈到使用上就是拖动进度条的同时,画面和声音都同步了。所以我们经常能听到的一个词是「多线程」,就是把一个程序分成多个任务去跑,让任务更快处理。不过线程和线程之间由于某些资源是独占的,会导致锁的问题。例如Python的GIL多线程锁。

协程

协程在线程中实现调度。你可以理解为它是 「微线程」 。它的调度不来自于CPU,而是完全来自于用户控制(可以理解为用代码控制流程)。协程的执行效率非常高,它的切换不是线程切换,没有线程切换的开销。而且只要线程越多,协程的性能优势就越明显。协程不需要多线程的锁机制,只需要判断状态即可。不过协程本身无法利用多核CPU,因为它基于线程,而线程又依赖于进程。

在JS里,常见的协程就是ES6的yield Generator或者ES7的async await。我们知道JS引擎是单线程的。所以在处理异步任务队列的时候,以往我们会陷入「回调金字塔」或者「回调地狱」。而有了协程之后我们可以在代码层面上来控制我们的程序。

比如我们有这么一个需求,等两个请求都返回之后,用它们的返回值共同做些事。(此处不用Promise.all()来实现,不是说不行,而是为了更好地说明主题)

ES6 + co 的写法:

1
2
3
4
5
6
7
const axios = require('axios')
const co = require('co')
co(function* (){
const getData = yield axios.get('xxx')
const postData = yield axios.post('xxx')
console.log(getData, postData)
})

ES7 的写法:

1
2
3
4
5
6
const axios = require('axios')
(async function () {
const getData = await axios.get('xxx')
const postData = await axios.post('xxx')
console.log(getData, postData)
})()

上述用「同步」的方式写的代码实际上依然是异步执行的。不过因为了有协程,在单线程的JS里也能够让我们在代码层面上实现了任务调度。

总结

可以说三者虽然是不同的东西,但是有着很密切的关系和类似的特性。它们的关系是从大到小,从上而下的。没有进程也就没有线程也就没有协程。总的来说,在多核处理器的情况下,多进程+多协程可以发挥最优的性能。

参考文献

  1. 进程,线程,协程与并行,并发
  2. 进程和线程、协程的区别
  3. 进程、线程和协程的比较
  4. 线程、进程与处理器
Author: Molunerfinn
Link: https://molunerfinn.com/process-thread-coroutine/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
支付宝打赏
微信打赏