进程是操作系统进行资源分配的基本单位,每个进程都有自己的独立内存空间。
由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
线程又叫轻量级进程,是进程的一个实体,是处理器任务调度和执行的基本单位。
它是比进程更小的能独立运行的基本单位。
线程自己不拥有资源,但它可与同属一个进程的线程共享进程所拥有的全部资源。
协程,又称微线程,是一种用户态的轻量级线程,协程的调度完全由用户控制(也就是在用户态执行)。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到线程的堆区,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
协程最大的优势就是协程极高的执行效率。
因为协程切换不是线程切换,而是由程序自身控制,因此没有线程切换的开销,和线程切换相比,线程数量越多,协程的性能优势就越明显。
不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高得多。
此外,一个线程的内存在 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,虚拟内存、文件等)。
进程和线程比较:
协程本质上就是用户态下的线程,所以也有人说协程是 “轻线程”,但我们一定要区分用户态和内核态的区别,很关键。