浅谈 Python 进程、线程和协程

引言

在任何语言的高性能编程中,必须要了解进程、线程和协程的关系。当然有些语言目前暂时还不支持协程,这边以 Python 为例子。

目前也是简单阐述,代码示例部分后期补上。

进程

进程是指在系统中正在运行的一个应用程序,是 CPU 的最小工作单元。

进程有就绪、运行、阻塞、创建和退出五种状态。其中,运行中的三种状态:就绪、运行、阻塞。创建和退出是描述产生和释放的状态。

特点

动态性:进程是程序的一次执行过程,动态产生,动态消亡。
独立性:进程是一个能独立运行的基本单元。是系统分配资源与调度的基本单元。
并发性:任何进程都可以与其他进程并发执行。
结构性:进程由程序、数据和进程控制块三部分组成。

缺点

无法即时完成的任务带来大量的上下文切换代价与时间代价。

进程的上下文:当一个进程在执行时, CPU 的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。
上下文切换:当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够得到切换时的状态并执行下去。

线程

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。
一个进程可以有一个或多个线程,同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。
但同一进程中的多个线程有各自的调用栈和线程本地存储。

说明:

进程才是 CPU 的最小作业单元(最小资源管理单元),开更多的线程不会导致本进程得到更多CPU的青睐,而是提高了 CPU 在本进程使用时间段的利用率。但是,本进程使用时间段的各线程优先级是用户可以自己设置的

对操作系统而言,线程是最小的执行单元,进程是最小的资源管理单元。无论是进程还是线 程,都是由操作系统所管理的。

协程

协程( Coroutine ,又称微线程,纤程)是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制。

如同一个进程可以有很多线程一样,一个线程可以有很多协程。

但是,协程不是被操作系统所管理的,没有改变 CPU 最小执行单元是线程,协程是完全由程序所控制的(用户态执行),不会产生上下文切换。

协程具有高并发、高扩展性、低成本的特点,一个 CPU 支持上万的协程都不是问题。所以,很适合用于高并发处理。通常,协程可以处理 IO 密集型程序的效率问题,但是处理 CPU 密集型不是它的长处,如要充分发挥 CPU 利用率可以结合多进程+协程。

优点

  • 无需线程上下文切换的开销
  • 无需原子操作锁定及同步的开销
  • 方便切换控制流,简化编程模型

缺点

  • 无法利用多核资源:协程的本质是个单线程,它不能同时在多个核用上。协程需要和进程配合才能运行在多 CPU 上。当然我们日常所编写的绝大部分应用都没有这个必要,除非是 CPU 密集型应用。
  • 进行阻塞( Blocking )操作(如 IO 时)会阻塞掉整个程序。

进程与线程的区别

  • 进程是 CPU 资源分配的基本单位,线程是独立运行和独立调度的基本单位( CPU 上真正运行的是线程)。
  • 进程拥有自己的资源空间,一个进程包含若干个线程,线程与 CPU 资源分配无关,多个线程共享同一进程内的资源。
  • 线程的调度与切换比进程快很多。
  • CPU 密集型代码(各种循环处理、计算等等):使用多进程。 IO 密集型代码(文件处理、网络爬虫等):使用多线程。

虽然线程大幅的提高了 CPU 的效率,且能够设置一定的优先级,但是线程的资源片分配还是由 CPU 来管理的。

进程、线程、协程的对比

  • 协程既不是进程也不是线程,协程仅是一个特殊的函数。协程、进程和线程不是一个维度的。
  • 一个进程可以包含多个线程,一个线程可以包含多个协程。虽然一个线程内的多个协程可以切换但是这多个协程是串行执行的,某个时刻只能有一个线程在运行,没法利用 CPU 的多核能力。
  • 协程与进程一样,也存在上下文切换问题。
  • 进程的切换者是操作系统,切换时机是根据操作系统自己的切换策略来决定的,用户是无感的。进程的切换内容包括页全局目录、内核栈和硬件上下文,切换内容被保存在内存中。 进程切换过程采用的是“从用户态到内核态再到用户态”的方式,切换效率低。
  • 线程的切换者是操作系统,切换时机是根据操作系统自己的切换策略来决定的,用户是无感的。线程的切换内容包括内核栈和硬件上下文。线程切换内容被保存在内核栈中。线程切换过程采用的是“从用户态到内核态再到用户态”的方式,切换效率中等。
  • 协程的切换者是用户(编程者或应用程序),切换时机是用户自己的程序来决定的。协程的切换内容是硬件上下文,切换内存被保存在用自己的变量(用户栈或堆)中。协程的切换过程只有用户态(即没有陷入内核态),因此切换效率高。

并发与并行

并发:在操作系统中,某一时间段,几个程序在同一个 CPU 上运行,但在任意一个时间点上,只有一个程序在该 CPU 上运行。

当有多个线程时,如果系统只有一个 CPU ,那么 CPU 不可能真正同时进行多个线程, CPU 的运行时间会被划分成若干个时间段,每个时间段分配给各个线程去执行,一个时间段里某个线程运行时,其他线程处于挂起状态,这就是并发。
并发解决了程序排队等待的问题,如果一个程序发生阻塞,其他程序仍然可以正常执行

并行:当操作系统有多个 CPU 时,一个 CPU 处理 A 线程,另一个 CPU 处理 B 线程,两个线程互相不抢占 CPU 资源,可以同时进行,这种方式成为并行。

并发与并行的区别

并发只是在宏观上给人感觉有多个程序在同时运行,但在实际的单 CPU 系统中,每一时刻只有一个程序在运行,微观上这些程序是分时交替执行。

在多 CPU 系统中,将这些并发执行的程序分配到不同的 CPU 上处理,每个 CPU 用来处理一个程序,这样多个程序便可以实现同时执行。

参考

Powered by Hexo and Hexo-theme-hiker

Copyright © 2018 - 2023 Leamx's Blog All Rights Reserved.

UV : | PV :