进程、线程与协程概念理解

一、进程

进程是一个具有一定独立功能的程序的一次动态执行过程,是操作系统进程资源分配的基本单位,通常包含三部分

  1. 程序
  2. 数据
  3. 程序控制块PCB:包含进程描述信息和控制信息

二、线程

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度的基本单位。

用户线程与内核线程

一对一模型

一个用户线程就唯一地对应一个内核线程,一个用户线程唯一地映射到一个物理CPU的内核线程。

优点:

  • 一个线程因某种原因阻塞时其他线程的执行不受影响
  • 让多线程程序在多处理器的系统上有更好的表现

缺点:

  • 用户线程的数量受到限制
  • 内核线程调度时,上下文切换的开销较大,导致用户线程的执行效率下降

多对一模型

将多个用户线程映射到一个内核线程上,线程之间的切换由用户态的代码来进行。

缺点:

  • 如果其中一个用户线程阻塞,那么其它所有线程都将无法执行,因为此时内核线程也随之阻塞
  • 在多处理器系统上,处理器数量的增加对多对一模型的线程性能不会有明显的增加,因为所有的用户线程都映射到一个处理器上

多对多模型

多对多模型结合了一对一模型和多对一模型的优点,将多个用户线程映射到多个内核线程上,由线程库负责在可用的可调度实体上调度用户线程,这使得线程的上下文切换非常快,因为它避免了系统调用。现流行的操作系统大多都采用多对多模型。

优点:

  • 一个用户线程的阻塞不会导致所有线程的阻塞,因为此时还有别的内核线程被调度来执行;
  • 多对多模型对用户线程的数量没有限制;
  • 在多处理器的操作系统中,多对多模型的线程也能得到一定的性能提升,但提升的幅度不如一对一模型的高。

协程

协程(Coroutines)是一种基于线程之上,但又比线程更加轻量,由程序员自己来管理的轻量级线程(用户空间线程)。

因为是自主开辟的异步任务,所以很多人把它们称为纤程(Fiber)。

为什么需要协程

背景:在传统的J2EE系统中都是基于每个请求占用一个线程去完成完整的业务逻辑,系统的吞吐能力取决于每个线程的操作耗时。如果遇到很耗时的I/O行为,则整个系统的吞吐立刻下降,因为这个时候线程一直处于阻塞状态,如果线程很多的时候,会存在很多线程处于空闲状态(等待该线程执行完才能执行)。

例子说明:JDBC是同步阻塞的,这也是说数据库是性能瓶颈的原因。这里的耗时其实是让CPU一直在等待I/O,线程没有使用CPU去做运算,而是处于空转状态。而过多的线程,也会带来更多的上下文切换开销。

对于上述问题,现阶段行业里的比较流行的解决方案之一就是单线程加上异步回调

而协程的目的则是当出现长时间的I/O操作时,通过让出目前的协程调度,执行下一个任务的方式,来消除上下文切换开销。

协程的特点

  1. 线程切换由操作系统调度,协程由用户调度,因此减少了上下文切换,提高了效率
  2. 线程的默认栈大小是1M,而协程更轻量,接近1K。因此可以在相同的内存中开启更多的协程
  3. 由于在同一个线程上,因此可以避免竞争关系而使用锁
  4. 适用于被阻塞的,且需要大量并发的场景。但不适用于大量计算的多线程,遇到此种情况,更好是用线程去解决。

协程的原理

当出现IO阻塞的时候,由协程的调度器进行调度,通过将数据流yield掉(主动让出),并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去跑,这样看上去好像跟写同步代码没有任何差别,这整个流程可以称为coroutine,而跑在由coroutine负责调度的线程称为纤程。

由于协程的暂停完全由程序控制,发生在用户态上;而线程的阻塞状态是由操作系统内核来进行切换,发生在内核态上。因此,协程的开销远远小于线程的开销。

posted @ 2023-10-23 01:58  ylyzty  阅读(4)  评论(0编辑  收藏  举报