当前位置: 首页 > news >正文

深入理解进程、线程与协程

引言

在现代计算机编程中,进程(Process)、线程(Thread)和协程(Coroutine)是三个核心的并发执行概念。理解它们之间的区别和联系,对于编写高效的并发程序至关重要。

一、进程(Process)

什么是进程?

进程是操作系统进行资源分配和调度的基本单位,是程序在计算机上的一次执行活动。当你双击打开一个应用程序时,操作系统就会创建一个进程。

进程的特点

  • 独立的内存空间:每个进程都拥有独立的地址空间,包括代码段、数据段、堆栈等
  • 资源隔离:进程间互不干扰,一个进程崩溃不会影响其他进程
  • 创建开销大:创建进程需要分配独立的内存空间,开销较大
  • 通信复杂:进程间通信(IPC)需要特殊机制,如管道、消息队列、共享内存等

进程示意图

┌─────────────────────────────────────────┐
│          操作系统(OS)                  │
├─────────────┬─────────────┬─────────────┤
│  进程 A     │  进程 B      │  进程 C     │
│ ┌─────────┐ │ ┌─────────┐ │ ┌─────────┐ │
│ │代码段    │ │ │代码段    │ │ │代码段    │ │
│ │数据段    │ │ │数据段    │ │ │数据段    │ │
│ │堆       │ │ │堆       │ │ │堆       │ │
│ │栈       │ │ │栈       │ │ │栈       │ │
│ └─────────┘ │ └─────────┘ │ └─────────┘ │
└─────────────┴─────────────┴─────────────┘独立内存       独立内存       独立内存

Python 进程示例

import multiprocessing
import osdef worker(name):print(f"进程 {name} 启动,PID: {os.getpid()}")if __name__ == '__main__':processes = []for i in range(3):p = multiprocessing.Process(target=worker, args=(f'Worker-{i}',))processes.append(p)p.start()for p in processes:p.join()

二、线程(Thread)

什么是线程?

线程是进程中的一个执行单元,是CPU调度的基本单位。一个进程可以包含多个线程,它们共享进程的资源。

线程的特点

  • 共享内存:同一进程内的线程共享进程的内存空间和资源
  • 轻量级:创建和切换开销比进程小得多
  • 通信简单:线程间可以直接访问共享变量
  • 同步问题:需要处理竞态条件、死锁等并发问题

线程示意图

┌────────────────────────────────────────┐
│             进程                       │
│  ┌──────────────────────────────────┐  │
│  │      共享内存空间                 │  │
│  │  ┌─────────┐  ┌─────────┐        │  │
│  │  │代码段    │  │数据段   │        │  │
│  │  └─────────┘  └─────────┘        │  │
│  └──────────────────────────────────┘  │
│                                        │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │线程 1    │  │线程 2   │  │线程 3   │ │
│  │栈+寄存器 │  │栈+寄存器 │ │栈+寄存器 │ │
│  └─────────┘  └─────────┘  └─────────┘ │
└────────────────────────────────────────┘

Python 线程示例

import threading
import timedef worker(name):print(f"线程 {name} 开始执行")time.sleep(2)print(f"线程 {name} 执行完毕")threads = []
for i in range(3):t = threading.Thread(target=worker, args=(f'Thread-{i}',))threads.append(t)t.start()for t in threads:t.join()

三、协程(Coroutine)

什么是协程?

协程是一种用户态的轻量级线程,由程序自己控制调度,而不是由操作系统内核调度。协程可以在执行过程中暂停,并在稍后恢复执行。

协程的特点

  • 超轻量级:创建成本极低,可以创建成千上万个协程
  • 用户态调度:不需要线程上下文切换,没有内核态和用户态的切换开销
  • 协作式调度:由程序员控制何时暂停和恢复
  • 适合 I/O 密集型:特别适合处理大量的网络请求或文件操作

协程示意图

线程
│
├── 协程 1  ─┐
│           ├──> 共享线程资源
├── 协程 2  ─┤
│           ├──> 无需操作系统调度
├── 协程 3  ─┤
│           └──> 用户态切换
└── 协程 N执行流程:
协程1 ━━━━╸ 暂停↓
协程2      ━━━━╸ 暂停↓
协程3           ━━━━╸ 暂停↓
协程1               ━━━━ 恢复执行

Python 协程示例(使用 asyncio)

import asyncioasync def worker(name, delay):print(f"协程 {name} 开始执行")await asyncio.sleep(delay)print(f"协程 {name} 执行完毕")return f"{name} 完成"async def main():# 创建多个协程任务tasks = [worker("Coroutine-1", 2),worker("Coroutine-2", 1),worker("Coroutine-3", 3),]# 并发执行所有协程results = await asyncio.gather(*tasks)print(f"所有结果: {results}")# 运行协程
asyncio.run(main())

四、三者对比

对比表格

特性进程线程协程
调度单位操作系统调度操作系统调度用户程序调度
资源占用大(MB级)中(KB级)小(字节级)
创建速度较快很快
切换开销
内存共享独立地址空间共享进程内存共享线程内存
通信方式IPC(复杂)共享内存(简单但需同步)直接访问
适用场景CPU密集型、需要隔离并行计算I/O密集型
数量限制受系统资源限制(几十到几百)受系统资源限制(几千)几乎无限制(几万到几十万)

使用场景建议

使用进程的场景:

  • 需要完全隔离的任务
  • CPU 密集型计算(可以利用多核 CPU)
  • 任务之间需要独立的内存空间

使用线程的场景:

  • 需要共享大量数据
  • 任务之间需要频繁通信
  • I/O 和计算混合的场景

使用协程的场景:

  • 大量的网络请求(如爬虫、API 服务)
  • 高并发 I/O 操作
  • 需要极高的并发数
  • WebSocket 长连接服务

五、实战案例:网络爬虫

使用多进程

import multiprocessing
import requestsdef fetch_url(url):response = requests.get(url)return len(response.content)if __name__ == '__main__':urls = ['http://example.com'] * 10with multiprocessing.Pool(4) as pool:results = pool.map(fetch_url, urls)print(f"总共下载: {sum(results)} 字节")

使用多线程

import threading
import requestsresults = []
lock = threading.Lock()def fetch_url(url):response = requests.get(url)with lock:results.append(len(response.content))urls = ['http://example.com'] * 10
threads = [threading.Thread(target=fetch_url, args=(url,)) for url in urls]for t in threads:t.start()
for t in threads:t.join()print(f"总共下载: {sum(results)} 字节")

使用协程

import asyncio
import aiohttpasync def fetch_url(session, url):async with session.get(url) as response:content = await response.read()return len(content)async def main():urls = ['http://example.com'] * 10async with aiohttp.ClientSession() as session:tasks = [fetch_url(session, url) for url in urls]results = await asyncio.gather(*tasks)print(f"总共下载: {sum(results)} 字节")asyncio.run(main())

六、总结

  1. 进程是资源分配的基本单位,提供完整的隔离和独立性
  2. 线程是 CPU 调度的基本单位,轻量级但需要处理同步问题
  3. 协程是用户态的调度单位,非常轻量,适合 I/O 密集型任务

选择哪种并发模型取决于你的具体需求:

  • 需要隔离和稳定性?选择进程
  • 需要共享数据和并行计算?选择线程
  • 需要高并发 I/O 处理?选择协程

在实际项目中,这三种技术往往会组合使用,充分发挥各自的优势。例如,可以使用多进程充分利用 CPU 核心,每个进程内使用协程处理大量的网络请求。


参考资源:

  • Python官方文档:multiprocessing、threading、asyncio
  • 操作系统原理相关书籍
  • 各语言的并发编程实践指南
http://www.dtcms.com/a/516158.html

相关文章:

  • 用IIS自带FTP功能搭一个FTP!
  • 一种简单的Yolov8 onnx模型类别标签获取的方法
  • 用哪个网站做首页好做网站哪里最便宜
  • ROS1+Vscode
  • Ubuntu22.04 中搭建基于 Qemu 的内核(驱动)开发环境
  • JMETER+ANT接口自动化测试环境搭建实战讲解
  • 告别“大力金刚指”:晶尊微触摸芯片让电梯按键一触即灵
  • HTML教程
  • 基于Qt Quick的图像标注与标注数据管理工具
  • vscode搭建python项目隔离的虚拟环境
  • 模版网站有源代码吗wordpress栏目对应模板
  • 海阳市城建设局网站网页价格表
  • 网站建设客户分析调查表wordpress打不开页面
  • JAVA算法练习题day50
  • xss-labs pass-10
  • ArcMap批量修改字段的属性值
  • 龙虎榜——20251022
  • 03-RAG Agent-集成百炼知识库(Spring AI Alibaba)
  • 基于DEIM模型的声纳图像目标检测系统设计与实现
  • 如何让新网站快速收录上海城乡建设管理局网站
  • SpringMVC—请求映射路径 get请求与Post请求发送请求参数 5种类型参数传递 json数据传递参数 日期型参数的传递 响应
  • 下一代医疗机器人的标配:六维力传感器破解远程医疗核心瓶颈
  • 内部网站建设要求广州哪家做网站最好
  • CCF-GESP 等级考试 2024年6月认证C++四级真题解析
  • 基于NLP进行文本内容预测常规流程
  • 建设银行手机网站变塘厦水霖学校
  • 音乐介绍网站怎么做抖音代运营介绍
  • 假数据神器JSONPlaceholder介绍(假数据接口、模拟数据接口、模拟测试接口、Mock data interface)
  • Alpha World:以结构化金融驱动Web3共识
  • 关于jsp网站开发的最新书籍厦门网站建设哪家便宜