通俗版解释(比喻法)
1. CPU 和核心
- CPU = 一个工厂(负责干活的总部)。
- 核心 = 工厂里的车间(比如工厂有4个车间,就能同时处理4个任务)。
2. 进程
- 进程 = 一家独立运营的公司(比如一家快递公司)。
- 每个公司有自己的资金、仓库、员工(独立资源)。
- 公司之间不能直接共享资源,要合作得打电话签合同(进程间通信)。
3. 线程
- 线程 = 同一家公司里的员工(比如快递公司的快递员)。
- 所有快递员共享公司的仓库和卡车(共享进程资源)。
- 快递员之间可以直接沟通,但抢同一辆卡车时要排队(需要锁机制)。
4. 协程
- 协程 = 一个超级快递员,能同时处理多个任务(比如一边送快递一边接电话)。
- 这个快递员很聪明,遇到红灯就停下,先处理另一个任务(遇到I/O阻塞就切换)。
- 但再厉害也只是一个人,没法变成两个快递员(无法利用多核)。
它们的关系
层级结构:
CPU(工厂)→ 核心(车间)→ 进程(公司)→ 线程(员工)→ 协程(超级员工)举个生活场景:
假设你要同时完成 做饭 和 接孩子放学:- 多进程:雇两个保姆(一个专门做饭,一个专门接孩子)→ 完全独立,但成本高。
- 多线程:一个保姆来回切换(先切菜,趁煮汤时跑出去接孩子)→ 省成本,但可能手忙脚乱。
- 协程:保姆用超高效的时间管理(切菜时预热点火,等水开的间隙打电话确认孩子位置)→ 适合需要频繁切换的小任务。
Python中的典型场景
场景1:计算圆周率(CPU密集型)→ 用多进程
# 目标:用多核加速计算
from multiprocessing import Pool
import math
def compute(n):
# 模拟复杂计算(比如计算圆周率的一部分)
return sum(math.sqrt(i) for i in range(n))
if __name__ == "__main__":
with Pool(4) as p: # 开4个进程(对应4核CPU)
result = p.map(compute, [10_000_000]*4) # 4个任务并行
print("总结果:", sum(result)) # 合并结果
场景2:下载10个网页(I/O密集型)→ 用协程
# 目标:同时等待多个网络请求
import asyncio
import aiohttp
async def download(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
print(f"{url} 下载完成,长度:{len(await response.text())}")
async def main():
urls = ["https://www.baidu.com"] * 10 # 10个相同网址
tasks = [download(url) for url in urls]
await asyncio.gather(*tasks) # 同时发起所有下载
asyncio.run(main()) # 总耗时 ≈ 下载1个网页的时间
场景3:边写文件边响应用户输入(简单多线程)
# 目标:不让写文件阻塞用户操作
import threading
def save_to_file():
# 模拟长时间写文件(比如写入1GB数据)
with open("bigfile.txt", "w") as f:
for _ in range(10_000_000):
f.write("data\n")
def listen_input():
while True:
cmd = input("输入命令:")
if cmd == "exit":
break
print("执行命令:", cmd)
# 启动两个线程
threading.Thread(target=save_to_file).start()
threading.Thread(target=listen_input).start()
终极总结表
适合场景 | Python模块 | 优点 | 缺点 | |
---|---|---|---|---|
多进程 | 大量计算 | multiprocessing | 绕过GIL锁,真并行 | 内存消耗大 |
多线程 | 中等并发I/O | threading | 共享数据方便 | 受GIL限制,不能加速计算 |
协程 | 超高并发I/O | asyncio | 轻量级,代码简洁 | 需要异步库支持 |
记住:计算用多进程,等I/O用协程,简单小任务用多线程。就像做饭时,煮汤(等I/O)时可以去切菜(协程切换),但没法一个人同时炒两锅菜(CPU计算)。