进程、线程、协程的区别
# 进程、线程、协程的区别
进程:Process,进程是资源分配的单位,使应用程序的执行副本,进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间。
线程:Thread,线程是 CPU 调度的单位,线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源。
协程:Routine 的一种实现,协程是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制,协程拥有自己的寄存器上下文和栈。
# CPU 最小的执行单位
进程需要管理:文件资源、硬件资源、权限信息、进程信息、CPU资源、内存分页等。
而执行只需要内存和 CPU,所以将执行的最小单位为抽象为线程。
操作系统调度的是自己的线程,再操作系统的线程表里;而 Java 会使用自己的 Java 线程,C 语言也会使用 C 线程。操作系统的线程才是真正的线程,它们才能真正的去执行。程序员创建的线程必须挂靠到操作系统的线程上。
# 线程与进程的区别
线程是进程内的一个执行单元,进程至少有一个线程,他们共享进程的地址空间,而进程有自己独立的地址空间。
进程是资源分配的单位,同一个进程内的线程共享进程资源。
线程是处理器调度的基本单位,而进程不是。
二者均可并发执行。
每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
# 协程与线程的区别
- 一个线程可以由多个协程,一个进程也可以单独拥有两个协程。
- 线程和进程都是同步机制,而协程是异步。
- 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。
- 线程是抢占式,而协程是非抢占式的,所以需要用户自己释放使用权来切换到其他协程,因此同一时间其实只有一个协程拥有运行权,相当于单线程的能力。
- 协程并不是取代线程,而且抽象于线程之上,线程是被分割的 CPU 资源,协程是组织好的代码流程,协程需要线程来承载运行,线程是协程的资源,但协程不会直接使用线程,协程直接利用的是执行器(Interceptor),执行器可以关联任意线程或线程池,可以使当前线程,UI 线程,或新建新程。
- 线程是协程的资源。协程通过 Interceptor 来间接使用线程这个资源。
大量的任务使用线程池中的线程,线程再挂靠到操作系统的线程上。
Thread 切换的成本比较高:内核需要中断、保存当前线程的状态、操作系统调度、加载 CPU 状态、中断、切换另一个线程。
如果大量的非常简短的高 IO 任务都需要使用线程,效率就会变得很低,切换的成本大于了执行任务的成本,切换很不划算。我们可以把大量的任务抽象成更小的模型 Routine,Routine 再去映射少量的线程,这少量的线程再去对应 Kernel的线程。
Routine 的切换不需要操作系统 Kernel,而是程序语言 Runtime 的行为,一个 Rouine发生 IO 时会主动让出执行权限,并通知 Skeduler 切换另一个 Routine 执行。这中间不会发生中断、线程的切换等。Routine 也可以称为轻量级的线程,Go 语言就支持 Routine。
协程就是 Routine 的一种实现。