浅析协程与线程与进程的区别和联系


内核线程

内核线程只运行在内核态,不受用户态上下文的拖累。

  • 处理器竞争:可以在全系统范围内竞争处理器资源;
  • 使用资源:唯一使用的资源是内核栈和上下文切换时保持寄存器的空间
  • 调度:调度的开销可能和进程自身差不多昂贵
  • 同步效率:资源的同步和数据共享比整个进程的数据同步和共享要低一些。

轻量级进程

轻量级进程(LWP)是建立在内核之上并由内核支持的用户线程,它是内核线程的高度抽象,每一个轻量级进程都与一个特定的内核线程关联。内核线程只能由内核管理并像普通进程一样被调度。

轻量级进程由clone()系统调用创建,参数是CLONE_VM,即与父进程是共享进程地址空间和系统资源。

与普通进程区别:LWP只有一个最小的执行上下文和调度程序所需的统计信息。

  • 处理器竞争:因与特定内核线程关联,因此可以在全系统范围内竞争处理器资源
  • 使用资源:与父进程共享进程地址空间
  • 调度:像普通进程一样调度

Linux使用的线程库

LinuxThreads是用户空间的线程库,所采用的是线程-进程1对1模型(即一个用户线程对应一个轻量级进程,而一个轻量级进程对应一个特定 的内核线程),将线程的调度等同于进程的调度,调度交由内核完成,而线程的创建、同步、销毁由核外线程库完成(LinuxThtreads已绑定到 GLIBC中发行)。

在LinuxThreads中,由专门的一个管理线程处理所有的线程管理工作。当进程第一次调用pthread_create()创建线程时就会先 创建(clone())并启动管理线程。后续进程pthread_create()创建线程时,都是管理线程作为pthread_create()的调用 者的子线程,通过调用clone()来创建用户线程,并记录轻量级进程号和线程id的映射关系,因此,用户线程其实是管理线程的子线程。

LinuxThreads只支持调度范围为PTHREAD_SCOPE_SYSTEM的调度,默认的调度策略是SCHED_OTHER。

用户线程调度策略也可修改成SCHED_FIFO或SCHED_RR方式,这两种方式支持优先级为0-99,而SCHED_OTHER只支持0。

  • SCHED_OTHER 分时调度策略,
  • SCHED_FIFO 实时调度策略,先到先服务
  • SCHED_RR 实时调度策略,时间片轮转

SCHED_OTHER是普通进程的,后两个是实时进程的(一般的进程都是普通进程,系统中出现实时进程的机会很少)。SCHED_FIFO、 SCHED_RR优先级高于所有SCHED_OTHER的进程,所以只要他们能够运行,在他们运行完之前,所有SCHED_OTHER的进程的都没有得到 执行的机会。

用户线程

用户线程是完全建立在用户空间的线程库,用户线程的创建、调度、同步和销毁全又库函数在用户空间完成,不需要内核的帮助。因此这种线程是极其低消耗和高效的。

  • 处理器竞争:单纯的用户线程是建立在用户空间,其对内核是透明的,因此其所属进程单独参与处理器的竞争,而进程的所有线程参与竞争该进程的资源。
  • 使用资源:与所属进程共享进程地址空间和系统资源。
  • 调度:由在用户空间实现的线程库,在所属进程内进行调度

协程

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

协程抽象于线程之上,线程是被分割的CPU资源, 协程是组织好的代码流程, 协程需要线程来承载运行。与线程相比,协程占用资源小,由用户调度,切换开销小,同一个线程中的协程不需要使用锁,执行效率更高。

进程、线程和协程的区别是什么?

进程是资源分配的最小单位,每个进程都有自己的独立内存空间,进程由进程控制块、程序段和数据段组成。

  • 进程控制块(PCB)保存进程运行期间相关的数据,是进程存在的唯一标志。
  • 程序段是能被进程调度程序调度到CPU 运行的程序的代码段。
  • 数据段用来存储程序运行期间的相关数据。

进程是应用程序运行的载体,可看做是正在执行的程序。程序本身是没有生命周期的,只是存在于磁盘上的一些指令集合,但程序一旦被运行起来就是进程。启动后的进程,会依赖操作系统的调度完成生命周期的转换。由于每个进程都有独立的代码和数据空间,所以进程间的切换会有较大的开销。

线程是CPU任务调度和执行的最小单位,一个进程中可以包含多个线程,这些线程可以并发运行,且共享进程提供的相同的代码和数据空间,每个线程都有自己独立的运行栈和程序计数器,线程间切换的开销小。

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

线程在进程的内部,它不能独立执行,必须依存于进程中,由进程提供多个线程的执行控制,进程和线程都可以并发的执行。

协程抽象于线程之上,线程是被分割的CPU资源, 协程是组织好的代码流程, 协程需要线程来承载运行。与线程相比,协程占用资源小,由用户调度,切换开销小,同一个线程中的协程不需要使用锁,执行效率更高。


文章作者: JoyTsing
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 JoyTsing !
评论
  目录