← 返回题目列表

Python 中线程和进程有什么区别?什么时候用多线程,什么时候用多进程?

高频 中等 第 9 / 27 题 更新于 2026/07/27
线程进程GIL并发模型

简化版

线程是同一进程内的执行流,共享内存,创建和切换成本较低,适合 I/O 密集任务;进程有独立内存空间,隔离性更好,成本更高,更适合 CPU 密集任务。由于 CPython 有 GIL,多线程通常不能让纯 Python CPU 密集代码真正并行,多进程更适合利用多核 CPU。

详细版

线程和进程可以从几个角度比较:

维度线程进程
内存空间同一进程内线程共享内存每个进程通常有独立地址空间
创建成本较低较高
通信方式共享变量、Queue、锁等Queue、Pipe、共享内存、文件、Socket 等
崩溃影响一个线程崩溃可能影响整个进程一个子进程崩溃通常更容易隔离
适合任务网络请求、文件 I/O、数据库 I/O图像处理、压缩、计算、模型推理等 CPU 密集任务

典型选择:

  • I/O 密集:多线程或异步 I/O;
  • CPU 密集:多进程,或交给释放 GIL 的 C 扩展、NumPy、外部服务;
  • 需要隔离:多进程;
  • 需要共享大量内存且逻辑简单:线程可能更方便,但必须处理同步问题。

示例:

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

def io_task(url):
    return fetch(url)

def cpu_task(n):
    return sum(i * i for i in range(n))

with ThreadPoolExecutor(max_workers=20) as pool:
    results = list(pool.map(io_task, urls))

with ProcessPoolExecutor(max_workers=4) as pool:
    results = list(pool.map(cpu_task, numbers))

面试时要说清:并发是同时处理多个任务,并行是同一时刻真正多个任务一起执行;Python 线程能提升 I/O 并发,但纯 Python CPU 并行通常要靠多进程。

完整版教学

一、先区分并发和并行

并发强调“同时处理多个任务”,并不要求同一时刻真的多个任务都在 CPU 上运行。一个线程等待网络返回时,另一个线程可以继续做别的事,这就是并发价值。

并行强调“同一时刻多个任务真正一起执行”,通常需要多核 CPU 或多台机器。

Python 面试里很多问题绕来绕去,其实都在问:你的任务到底是 I/O 等待多,还是 CPU 计算多?

二、线程为什么适合 I/O 密集任务

I/O 密集任务的大量时间花在等待外部资源:

  • 等网络响应;
  • 等数据库返回;
  • 等磁盘读写;
  • 等第三方接口。

等待期间 CPU 是空的。多线程可以让一个线程等待 I/O 时,另一个线程继续运行。

from concurrent.futures import ThreadPoolExecutor

def download(url):
    return request_url(url)

with ThreadPoolExecutor(max_workers=20) as pool:
    for content in pool.map(download, urls):
        handle(content)

即使存在 GIL,I/O 等待期间线程通常会释放执行机会,所以多线程仍然能显著提升吞吐。

三、进程为什么适合 CPU 密集任务

CPU 密集任务主要消耗 CPU,比如:

  • 大量数学计算;
  • 图片压缩;
  • 视频转码;
  • 纯 Python 循环计算;
  • 加密解密、解析大量数据。

在 CPython 中,GIL 会让同一进程内多个 Python 线程执行字节码时互相竞争。纯 Python CPU 密集任务用多线程不一定更快,甚至可能因为线程切换更慢。

多进程有独立解释器和独立 GIL,可以更好利用多核:

from concurrent.futures import ProcessPoolExecutor

def compute(n):
    return sum(i * i for i in range(n))

with ProcessPoolExecutor(max_workers=4) as pool:
    results = list(pool.map(compute, [10_000_000] * 8))

四、共享内存是优点也是风险

线程共享同一进程内的对象,传数据很方便:

items.append(value)

但共享也意味着竞争。多个线程同时修改同一个对象,可能导致数据错乱,需要 Lock、Queue 等同步工具。

进程之间默认不共享普通对象,隔离性更好,但通信成本更高。传给子进程的数据通常需要序列化,这对大对象会有明显开销。

五、工程中怎么做选择

可以按这个顺序判断:

  1. 任务主要在等外部资源吗?优先线程池或异步 I/O;
  2. 任务主要在吃 CPU 吗?优先进程池;
  3. 是否要强隔离,避免某个任务拖垮主进程?倾向进程;
  4. 是否需要频繁共享大量状态?线程更方便,但同步复杂;
  5. 是否已经使用 NumPy、Pandas 等释放 GIL 的 C 扩展?线程也可能有效。

这个判断比背“线程轻、进程重”更有面试价值。

六、常见误区与追问

维度线程进程
地址空间同进程内共享默认相互隔离
切换和创建成本较低较高
CPython CPU 并行受 GIL 限制可利用多核
适合任务I/O 密集、等待多CPU 密集、隔离要求高
  • 误区:并发和并行是同一个概念。 并发强调任务交替推进,并行强调同一时刻真的同时执行;单核也能并发,多核才更容易并行。
  • 误区:Python 线程完全没有价值。 I/O 阻塞期间线程可以切换,网络请求、文件等待、数据库调用等场景仍可能明显受益。
  • 误区:进程一定适合所有高并发任务。 进程隔离好但成本高,海量短 I/O 任务用进程可能浪费内存和调度资源。
  • 追问:为什么 CPU 密集任务常用多进程? CPython 的 GIL 限制同一进程内多个 Python 线程同时执行字节码,多进程能让多个解释器进程分布到多核。
  • 追问:线程共享内存是优点还是风险? 两者都是:共享让通信简单,但共享可变状态需要锁,否则容易竞态。
  • 追问:工程上如何回答选择题? 先判断任务瓶颈是等待 I/O 还是消耗 CPU,再看数据共享、隔离、启动成本和部署资源。

记忆钩子:线程省成本、适合等 I/O;进程隔离强、适合吃 CPU;别把“并发”和“并行”混着答。

七、加强记忆

线程轻、共享内存、适合 I/O;进程重、隔离性强、适合 CPU。Python 里还要补上 GIL 这个限制:多线程不是纯 Python CPU 密集任务的多核加速器,但对 I/O 并发依然很有用;要跑满多核,通常选择多进程或释放 GIL 的底层扩展。