进程、线程、协程的区别
进程
是操作系统对一个正在运行的程序的一种抽象,是系统进行资源分配和调度的一个独立单位。
多进程:为了提高CPU的利用率,当某个进程阻塞之后可以运行另一个进程,让计算机可以在单CPU并发运行多个进程,出现了多道程序设计(Linux中采用的是时间片和优先级的公平调度算法)
。
但多进程的缺点是进程切换的开销大,因为进程切换时需要保存当前进程的状态,加载新进程的状态,这个过程需要耗费大量的CPU时间。
线程
线程的引入是为了减少进程切换的开销。
线程是进程的一部分,一个进程可以包含多个线程,线程是CPU调度的基本单位。
进程和线程在Linux中都是通过task_struct
结构体来表示的,但是进程和线程的区别在于task_struct
结构体中的mm
字段,进程的mm
字段指向的是一个mm_struct
结构体,而线程的mm
字段指向的是和其他线程共享的mm_struct
结构体。
进程切换时需要切换mm_struct
结构体,而线程切换时不需要切换mm_struct
结构体,所以线程切换比进程切换的代价小。
协程
协程的引入是为了减少线程切换的开销。
线程的创建和销毁都需要系统调用,如果每次请求都创建新的线程,在高并发下开销会非常大,而且线程占用的内存是MB级别,数量也不能太多。 而且当线程越多,那么CPU切换也会越多,因为系统调用需要保证线程的公平调度,就需要不停进行线程切换,这样会导致CPU开销增大。 协程便是主要为了解决上面两个问题:
- 降低内存占用,减少创建的开销
- 减少上下文切换的开销
首先,协程是一个用户态的线程,只是一个数据结构 + 一套操作系统调度的算法,不需要系统调用,所以创建和销毁的开销非常小,占用的内存也非常小,达到KB级别。
而协程本质还是线程,只是在用户态实现了线程的调度,所以切换开销在用户态是无法降低的,为了减少上下文切换的开销,只能减少上下文切换的次数。
- 让一个线程执行多个任务,减少可执行的线程的数量
- 让线程尽可能处于可执行状态,减少线程的阻塞时间