天机阁

进程、线程、协程的区别

2022-07-10 · 5 min read
操作系统

什么是进程?

进程是操作系统进行资源分配的基本单位,每个进程都有自己的独立内存空间。
由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。

什么是线程?

线程又叫轻量级进程,是进程的一个实体,是处理器任务调度和执行的基本单位。
它是比进程更小的能独立运行的基本单位。
线程自己不拥有资源,但它可与同属一个进程的线程共享进程所拥有的全部资源。

什么是协程?

协程,又称微线程,是一种用户态的轻量级线程,协程的调度完全由用户控制(也就是在用户态执行)。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到线程的堆区,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

协程最大的优势就是协程极高的执行效率。
因为协程切换不是线程切换,而是由程序自身控制,因此没有线程切换的开销,和线程切换相比,线程数量越多,协程的性能优势就越明显。
不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高得多。
此外,一个线程的内存在 MB 级别,而协程只需要 KB 级别。

进程和线程的区别

对于操作系统来说,一个任务就是一个进程(Process)。比如打开一个浏览器就是启动了一个浏览器进程,打开一个记事本就是启动了一个记事本进程,打开两个记事本就是启动了两个记事本进程。

有些进程同时还不止干一件事,比如 Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,进程内的这些“子任务”称为线程(Thread)。

由于每个进程至少要干一件事,所以一个进程至少有一个线程。

每个线程都是一个轻量级进程(Light Weight Process),都有自己的唯一 PID 和 一个 TGID(Thread Group ID)。TGID是启动整个进程的 thread 的 PID。

例如,当一个进程被创建的时候,它其实是一个PID和TGID数值相同线程。当线程A启动线程B时,线程B会有自己的唯一PID,但它的TGID会从A继承而来。这样通过PID线程可以独立得到调度,而相同的TGID可以知道哪些线程属于同一个进程,这样可以共享资源(RAM,虚拟内存、文件等)。

进程和线程比较:

  1. 调度。线程是独立调度的基本单位,进程是拥有资源的基本单位。在同一进程中,线程的切换不会引起进程切换。在不同进程进行线程切换,会引起进程切换。
  2. 拥有资源。进程是拥有资源的基本的单位,而线程不拥有系统资源。但线程可以访问其隶属进程的系统资源。
  3. 并发性。进程之间可以并发执行,多个线程之间也可以并发执行。
  4. 系统开销。创建或撤销进程所付出的开销远大于创建或撤销线程时的开销。
  5. 进程地址和其他资源。同一进程的各线程间共享进程的资源,某进程内的线程对于其他进程不可见。
  6. 通信方面。进程间通信需要进程同步或互斥手段的辅助,以保证数据的一致性,而线程间可以直接读/写进程数据段来进行通信。

协程和线程的区别

  1. 节省 CPU:避免系统内核级的线程频繁切换,造成的 CPU 资源浪费。好钢用在刀刃上。而协程是用户态的线程,用户可以自行控制协程的创建于销毁,极大程度避免了系统级线程上下文切换造成的资源浪费。
  2. 节约内存:在 64 位的Linux中,一个线程需要分配 8MB 栈内存和 64MB 堆内存,系统内存的制约导致我们无法开启更多线程实现高并发。而在协程编程模式下,可以轻松有十几万协程,这是线程无法比拟的。
  3. 稳定性:前面提到线程之间通过内存来共享数据,这也导致了一个问题,任何一个线程出错时,进程中的所有线程都会跟着一起崩溃。
  4. 开发效率:使用协程在开发程序之中,可以很方便的将一些耗时的IO操作异步化,例如写文件、耗时 IO 请求等。

协程本质上就是用户态下的线程,所以也有人说协程是 “轻线程”,但我们一定要区分用户态和内核态的区别,很关键。