进程、线程、协程三者的区别和联系

作者:爱学习的小道长日期:2025/11/23

1. 核心概念对比

特性维度进程 (Process)线程 (Thread)协程 (Coroutine)
基本定义资源分配的基本单位,拥有独立的地址空间CPU调度的基本单位,共享进程的资源用户态的轻量级线程,在单线程内通过协作进行任务切换
隔离性强,一个进程崩溃通常不会影响其他进程弱,一个线程崩溃可能导致整个进程退出,影响同进程所有线程。无,所有协程在同一线程内运行。
开销大,创建、销毁和上下文切换(涉及页表、寄存器等)成本高。中等,创建和切换开销比进程小,但仍需内核介入。极小,切换由程序控制,无需内核参与,只需保存少量寄存器上下文。
数据共享复杂,需要进程间通信(IPC),如管道、消息队列、共享内存。简单,可直接读写进程的全局变量和堆内存,但需同步机制(如锁)。极简单,可直接访问共享变量,通常在单线程内通过事件循环协作,无需锁。
并发性多进程可利用多核CPU实现真正并行。多线程可并发,但因GIL限制,在CPython中难以充分利用多核进行CPU计算。单线程内可实现极高并发,尤其适合I/O密集型任务。
Python库multiprocessingthreadingasyncio

2. 三者间的联系

尽管存在差异,但进程、线程和协程之间存在着清晰的层次和协作关系

  • 包含关系:一个操作系统由多个进程组成;一个进程包含一个或多个线程;一个线程可以运行成千上万个协程。
  • 协作共存:现代复杂应用(如Nginx、数据库)常采用混合模型。例如,采用多进程架构保证稳定性,每个进程内使用多线程处理事务,而在线程内部又使用协程来处理海量网络连接,以兼顾隔离性、效率和并发能力

3. python 代码

在Python中,multiprocessing、threading和asyncio这三个库分别是处理进程、线程和协程的核心工具。

3.1 简单代码

  1. 使用 multiprocessing进行CPU密集型计算
    multiprocessing通过创建子进程绕过GIL限制,充分利用多核CPU,适合计算密集型任务
1import multiprocessing
2import time
3from typing import List
4
5def calculate_square_chunk(chunk: List[int]) -> List[int]:
6    """计算列表中数字的平方(分块处理)"""
7    return [n * n for n in chunk]
8
9def calculate_square_no_process(numbers: List[int]) -> float:
10    """不使用多进程的计算函数"""
11    start_time = time.time()
12    result = [n * n for n in numbers]
13    end_time = time.time()
14    execution_time = end_time - start_time
15    print(f"非多进程执行时间: {execution_time:.6f} 秒")
16    return execution_time
17
18def calculate_with_multiprocessing_pool(numbers: List[int], num_processes: int = None) -> float:
19    """使用进程池进行多进程计算"""
20    if num_processes is None:
21        num_processes = multiprocessing.cpu_count()
22    
23    print(f"使用 {num_processes} 个进程")
24    
25    # 将数据分成多个块
26    chunk_size = len(numbers) // num_processes
27    chunks = [numbers[i:i + chunk_size] for i in range(0, len(numbers), chunk_size)]
28    
29    start_time = time.time()
30    
31    with multiprocessing.Pool(processes=num_processes) as pool:
32        results = pool.map(calculate_square_chunk, chunks)
33    
34    # 合并结果(如果需要的话)
35    final_result = []
36    for chunk_result in results:
37        final_result.extend(chunk_result)
38    
39    multiprocess_time = time.time() - start_time
40    return multiprocess_time
41
42def calculate_with_single_process(numbers: List[int]) -> float:
43    """使用单个进程进行计算(对比基准)"""
44    start_time = time.time()
45    
46    p = multiprocessing.Process(target=calculate_square_chunk, args=(numbers,))
47    p.start()
48    p.join()
49    
50    return time.time() - start_time
51
52if __name__ == '__main__':  
53    # 优化数据生成,使用更合理的数据量
54    base_numbers = list(range(1, 21))
55    numbers = base_numbers * 2000000  # 调整为更合理的数量
56    
57    print(f"数据量: {len(numbers):,} 个元素")
58    print(f"CPU核心数: {multiprocessing.cpu_count()}")
59    print(f"\n内存使用:")
60    print(f"原始数据大小: {len(numbers) * 4 / (1024*1024):.1f} MB")
61    
62    # 测试1: 不使用多进程
63    print("\n=== 测试1: 不使用多进程 ===")
64    non_multiprocess_time = calculate_square_no_process(numbers)
65    
66    # 测试2: 使用进程池(多进程)
67    print("\n=== 测试2: 使用进程池(多进程) ===")
68    multiprocess_pool_time = calculate_with_multiprocessing_pool(numbers)
69    print(f"多进程池执行时间: {multiprocess_pool_time:.6f} 秒")
70    
71    # 测试3: 使用单个进程(对比)
72    print("\n=== 测试3: 使用单个进程(对比) ===")
73    single_process_time = calculate_with_single_process(numbers)
74    print(f"单进程执行时间: {single_process_time:.6f} 秒")
75    
76    # 性能比较
77    print("\n=== 性能比较 ===")
78    print(f"非多进程 vs 多进程池: {non_multiprocess_time/multiprocess_pool_time:.2f}x 加速")
79    print(f"单进程 vs 多进程池: {single_process_time/multiprocess_pool_time:.2f}x 加速")
80

输出结果:

1数据量: 40,000,000 个元素
2CPU核心数: 16
3
4内存使用:
5原始数据大小: 152.6 MB
6
7=== 测试1: 不使用多进程 ===
8非多进程执行时间: 0.579534 
9
10=== 测试2: 使用进程池(多进程) ===
11使用 16 个进程
12多进程池执行时间: 1.508401 
13
14=== 测试3: 使用单个进程(对比) ===
15单进程执行时间: 0.715703 
16
17=== 性能比较 ===
18非多进程 vs 多进程池: 0.38x 加速
19单进程 vs 多进程池: 0.47x 加速
20
  1. 使用 asyncio处理高并发I/O操作
    asyncio非常适合I/O密集型任务,如网络请求、文件读写等,能在单线程内实现高并发
1import asyncio
2import time
3
4async def say_after(delay, what):
5    await asyncio.sleep(delay)  # 模拟I/O操作,如网络请求
6    print(what)
7
8async def main():
9    print(f"Started at {time.strftime('%X')}")
10    start_time = time.time()
11    # 顺序执行两个协程
12    await say_after(1, 'Hello')
13    await say_after(2, 'World')
14    
15    print(f"Finished at {time.strftime('%X')}")
16    total_time = time.time() - start_time
17    
18    print(f"顺序执行时间: {total_time:.4f} 秒")
19
20# 运行异步主函数
21asyncio.run(main())
22

输出:

1Started at 16:22:11
2Hello
3World
4Finished at 16:22:14
5顺序执行时间: 3.0037 
6

上面的例子是顺序执行,asyncio的强大之处在于能并发执行多个I/O任务:

1import asyncio
2import  time
3
4async def fetch_data(task_id, seconds):
5    print(f"Task {task_id} started.")
6    await asyncio.sleep(seconds)  # 模拟耗时的I/O操作
7    print(f"Task {task_id} completed after {seconds} second(s).")
8    return f"Data from task {task_id}"
9
10async def main():
11    # 创建多个任务并发执行
12    print(f"Started at {time.strftime('%X')}")
13    start_time = time.time()
14    tasks = [
15        asyncio.create_task(fetch_data(1, 2)),
16        asyncio.create_task(fetch_data(2, 1)),
17        asyncio.create_task(fetch_data(3, 3))
18    ]
19    
20    # 等待所有任务完成并收集结果
21    results = await asyncio.gather(*tasks)
22    total_time = time.time() - start_time
23    print(f"Finished at {time.strftime('%X')}")
24    print(f"Total time taken: {total_time:.4f} seconds")
25    print(f"All tasks done. Results: {results}")
26
27asyncio.run(main())
28

输出结果:

1Started at 16:29:31
2Task 1 started.
3Task 2 started.
4Task 3 started.
5Task 2 completed after 1 second(s).
6Task 1 completed after 2 second(s).
7Task 3 completed after 3 second(s).
8Finished at 16:29:34
9Total time taken: 3.0019 seconds
10All tasks done. Results: ['Data from task 1', 'Data from task 2', 'Data from task 3']
11
  1. 多线程生产环境使用ThreadPoolExecutor
1from concurrent.futures import ThreadPoolExecutor
2import time
3import random
4
5def process_item(item):
6    """处理单个项目的函数"""
7    process_time = random.uniform(0.5, 2.0)
8    time.sleep(process_time)
9    result = f"已处理: {item} (耗时: {process_time:.2f}秒)"
10    return result
11
12def main():
13    # 要处理的项目列表
14    items = [f"项目--> {i}" for i in range(1,13)]
15    
16    # 使用线程池(最大4个线程)
17    with ThreadPoolExecutor(max_workers=4) as executor:
18        # 提交所有任务
19        future_to_item = {
20            executor.submit(process_item, item): item 
21            for item in items
22        }
23        
24        # 收集结果
25        results = []
26        for future in future_to_item:
27            try:
28                result = future.result()
29                results.append(result)
30                print(result)
31            except Exception as e:
32                print(f"处理出错: {e}")
33    
34    print(f"\n总共处理了 {len(results)} 个项目")
35
36if __name__ == "__main__":
37    main()
38

输出:

1已处理: 项目--> 2 (耗时: 1.77秒)
2已处理: 项目--> 3 (耗时: 0.63秒)
3已处理: 项目--> 4 (耗时: 1.06秒)
4已处理: 项目--> 5 (耗时: 1.11秒)
5已处理: 项目--> 6 (耗时: 1.22秒)
6已处理: 项目--> 7 (耗时: 1.08秒)
7已处理: 项目--> 8 (耗时: 1.04秒)
8已处理: 项目--> 9 (耗时: 0.99秒)
9已处理: 项目--> 10 (耗时: 1.67秒)
10已处理: 项目--> 11 (耗时: 1.56秒)
11已处理: 项目--> 12 (耗时: 0.93秒)
12
13总共处理了 12 个项目
14

3. 实战建议与选型

在实际项目中如何选择?下面这个决策树可以帮你快速判断

  1. 任务是CPU密集型吗?(例如,计算圆周率、数据编码/解码、图像处理)
    是​ → 选择 multiprocessing。创建多个进程,充分利用多核CPU。
    否(是I/O密集型,如网络爬虫、Web服务、数据库查询)→ 进入第2步。
  2. 需要处理非常高并发(如超过1000)的连接吗?并且希望代码效率最高、开销最小?
    是​ → 选择 asyncio(协程)。单线程内处理海量连接,切换开销极小。
    否(并发量不高,或对代码结构有偏好)→ 进入第3步。
  3. I/O操作是阻塞式的吗?(例如,使用了一些不支持异步的传统库)
    是,且不想或不能修改​ → 选择 threading(线程)。线程池是一个简单有效的选择。
    否,或愿意使用异步库​ → 仍然推荐 asyncio,因为它通常能提供更好的性能。

简单来说
计算用进程:把繁重的计算任务分给多个进程并行处理。
I/O用协程:在等待网络、磁盘时,用协程并发处理其他任务,效率最高。
兼容用线程:当遇到不支持异步的库时,线程是折中方案。


进程、线程、协程三者的区别和联系》 是转载文章,点击查看原文


相关推荐


Redis(136)Redis的客户端缓存是如何实现的?
Victor3562025/11/21

Redis 的客户端缓存(Client-Side Caching)是一项重要特性,允许客户端在本地缓存 Redis 数据,从而减少与 Redis 服务器的通信频率,提高应用的响应速度和可扩展性。Redis 客户端缓存的实现主要依赖于以下几个核心组件和机制: 订阅机制:客户端通过订阅特定的键空间事件,获取键的变更通知。 通知机制:Redis 服务器在键发生变更时,通过发布/订阅(Pub/Sub)机制将变更通知推送给客户端。 缓存一致性:确保客户端缓存与 Redis 服务器的数据一致性。 核心概


【AI省流快讯】Cloudflare 炸了 / Gemini 3 来了 / Antigravity 独家实测 (附:无法登录解法)
coder_pig2025/11/19

1. Cloudflare 挂了 🤡 昨晚陆续刷到 "CF挂了" 的消息,没太在意,直到无法打开" 盗版漫画" 站点,我才意识到问题的严重性: 🤣 原因众说纷纭,刷到这哥们的 "梗图",差点把我笑岔气: 😃 还有人猜测可能是 Google 发布的 "哈基米 3" (Gemini) 发起的攻击: 时间线: 【19:30】用户开始报告网站无法访问,出现10xx、52x、50x系列错误;Cloudflare Dashboard无法访问;部分Cloudflare域名解析中断。 【19:4


Excel处理控件Aspose.Cells教程:使用Python从Excel工作表中删除数据透视表
IT开发者笔记2025/11/18

在使用 Excel 处理数据时,数据透视表通过汇总大型数据集,简化了分析过程。但随着分析的深入,您可能需要删除旧的数据透视表,以保持工作表的整洁或为新的分析结果做好准备。您可以快速删除任何数据透视表,无需手动查找,也不会留下任何失效的引用。本教程将逐步介绍如何借助Aspose.Cells使用Python从Excel 工作表中删除数据透视表。 Aspose.Cells官方试用版免费下载 本篇教程适合: 使用Excel高级用户自动生成每月演示文稿每周一都要重建仪表盘的数据分析师宁愿写五行代码也


用 TRAE SOLO 高效开发的 12 个小技巧
TRAE_ai2025/11/17

本文作者:云舒,TRAE 产品运营 用 SOLO 高效开发的 12 个技巧,从入门到精通,带你玩转 SOLO。 第一部分:入门篇 技巧 1:根据项目需求选择合适的内置智能体 TRAE SOLO 内置了两个核心智能体:SOLO Coder和 SOLO Builder,它们分别适用于不同的开发场景,明确场景后选择合适的智能体,能显著提升推进效率与结果质量。 如果你想处理基于现有代码库的迭代、重构和 Bug 修复等复杂任务,SOLO Coder 是最佳的选择,它具备优秀的项目理解和上下文管理能力


linux之ubuntu qt界面开发开发点菜系统
RouDragon2025/11/16

首先这篇博客主要讲解的是如何设计一个基于qt开发的点菜系统,这方面有很多内容会引用他人的文章需要继续学习他人的文章才会明白此文章是在讲解啥。 自制点菜系统视频链接 整体设计思路     这张图其实很详细的介绍了点菜系统需要的技术,在开发板方面,也就是服务器端,首先屏幕显示也是基于qt开发,所有你的ubuntu qt开发的时候就得设置好其编译器和环境基于开发板的,同时你还需要另一套环境进行直接在开发板上测试不需要反反复复的在开发板上重装。屏幕显示部分还需要首先设置一个登陆界面当客户


进入职场第五课——突破和跃升
Mapbarfront2025/11/14

观察、融入、立足、产出,度过这4个阶段之后,你已经稳稳地,成为团队里的主力输出了,接下来,如果你想从团队中的好员工,跃升为老板眼中的关键人物,从业务骨干到真正的团队核心,必须要做的下一步就是突破,易经乾卦中的或跃在渊,说的就是这个意思。 或是或许,代表着不确定性,跃是跳跃,代表着勇敢一搏,在渊是指在深渊里,代表着突破前在深渊里的等待,这个阶段,是你在积蓄了足够的力量之后,遇到合适的机会纵身一跃的时刻,这是审慎的冒险,也是耐心等待之后的水到渠成,想要完成这次关键的进阶,以下这5个动作,你要步步为营


uos基础 dmesg 查看内核的实时日志
行初心2025/11/13

统信桌面操作系统专业版V20(1070) Linux uos 5.10.97-arm64-desktop uos基础 dmesg 查看内核的实时日志 root@uos:~# dmesg -wH [11月10 14:59] [pid:3256,cpu1,Xwayland,1][HISI_DRM_HEAPS D]:do_alloc_memory: need alloc size=0x3000, now pool size=0x1a60000 [ +0.000000] [pid:3256,cpu1


苹果上线App Store Web版本,以后浏览外区更方便了
CocoaKier2025/11/12

近期,苹果低调上线了网页版 App Store(apps.apple.com/cn) 只要打开浏览器,用户就可以浏览AppStore了,即便非苹果设备也能访问,但目前只能浏览、搜索,不支持在网页端下载 app。 网页版的一个亮点是支持快速切换区域,我们只需修改网页地址中的区域代码即可快速浏览其他地区的 App Store 内容。这对于竞品分析,特别是出海产品的竞品分析,带来了非常大的便利,可以更方便快捷地查看某个国家地区的榜单,同类型应用有哪些,某个应用在不同地区的可用性、价格、评分、评论情况。


Day 7:05. 基于Nuxt开发博客项目-首页开发
申阳2025/11/10

一、前言 首页是站点的“脸面”,也是信息传达最直接的窗口。首页的设计质量,不仅关系到用户对站点的第一印象,更直接影响其使用体验与整体评价。因此,精心打造首页,至关重要。 我其实比较反感一些花里胡哨的页面,但是恰到好处的动画确实可以提高用户的体验,也利于网站推广。 我的目标是寻求平衡,信息作为主导,动画作为辅助。 下面开始我们的首页打造吧。 二、渐变文字标题 在tailwindcss的加持下,实现这种效果太方便了,只需要以下几个指令即可 <span class="ml-1 font-bold t


猿族代码战记:Mutex 升级版——守护 Swift 并发的“香蕉仓库”
大熊猫侯佩2025/11/8

🦍 引子 旧金山废墟的猿族技术区,金属支架撑起的荧光屏泛着冷光,首席 Swift 架构师科巴的指节因攥紧终端而发白 —— 食物计数系统又出问题了。 刚录入的 27 根香蕉,刷新页面竟变成 29,再点一下又跳回 28,旁边年轻猿工程师紧张地挠着头:“科巴大人,不会是小猩猩偷偷改数据吧?” 科巴瞪了他一眼:“是‘并发幽灵’!自从用 Actor 保护状态,简单的计数全成了麻烦 —— 查个库存要写await,就像咱们去仓库拿根香蕉,得先找凯撒签字、找后勤登记,折腾半小时!” 在本堂猩猩课堂中,您将学

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读