通俗版解釋(比喻法)
1. CPU 和核心
- CPU = 一個工廠(負責干活的總部)。
- 核心 = 工廠里的車間(比如工廠有4個車間,就能同時處理4個任務)。
2. 進程
- 進程 = 一家獨立運營的公司(比如一家快遞公司)。
- 每個公司有自己的資金、倉庫、員工(獨立資源)。
- 公司之間不能直接共享資源,要合作得打電話簽合同(進程間通信)。
3. 線程
- 線程 = 同一家公司里的員工(比如快遞公司的快遞員)。
- 所有快遞員共享公司的倉庫和卡車(共享進程資源)。
- 快遞員之間可以直接溝通,但搶同一輛卡車時要排隊(需要鎖機制)。
4. 協程
- 協程 = 一個超級快遞員,能同時處理多個任務(比如一邊送快遞一邊接電話)。
- 這個快遞員很聰明,遇到紅燈就停下,先處理另一個任務(遇到I/O阻塞就切換)。
- 但再厲害也只是一個人,沒法變成兩個快遞員(無法利用多核)。
它們的關系
-
層級結構:
CPU(工廠)→ 核心(車間)→ 進程(公司)→ 線程(員工)→ 協程(超級員工) -
舉個生活場景:
假設你要同時完成 做飯 和 接孩子放學:- 多進程:雇兩個保姆(一個專門做飯,一個專門接孩子)→ 完全獨立,但成本高。
- 多線程:一個保姆來回切換(先切菜,趁煮湯時跑出去接孩子)→ 省成本,但可能手忙腳亂。
- 協程:保姆用超高效的時間管理(切菜時預熱點火,等水開的間隙打電話確認孩子位置)→ 適合需要頻繁切換的小任務。
Python中的典型場景
場景1:計算圓周率(CPU密集型)→ 用多進程
# 目標:用多核加速計算
from multiprocessing import Pool
import mathdef 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 aiohttpasync 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 threadingdef 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":breakprint("執行命令:", 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計算)。