目錄
一、多任務基礎:并發與并行
1. 什么是多任務
2. 兩種表現形式
二、進程:操作系統資源分配的最小單位
1. 進程的概念
2. 多進程實現多任務
2.1 基礎示例:邊聽音樂邊敲代碼
2.2 帶參數的進程任務
2.3 進程編號與應用注意點
2.3.1 進程編號的作用
2.3.2 關鍵注意點
三、線程:程序執行的最小單位
1. 線程的概念
2. 多線程實現多任務
3. 線程的核心特性
四、進程與線程的對比
五、協程:用戶態的輕量級線程
1. 協程的概念
2. 核心優勢
3. 基于asyncio實現協程
4. 協程的適用場景與注意事項
六、總結:如何選擇多任務方案
在日常開發中,我們經常會遇到需要同時處理多個任務的場景,比如網盤同時下載多個文件、程序一邊播放音樂一邊執行計算。這些都離不開多任務編程技術。本文將基于 Python,從多任務的基礎概念出發,詳細講解進程、線程與協程三種實現方式,幫助你輕松掌握多任務編程的核心邏輯。
一、多任務基礎:并發與并行
1. 什么是多任務
多任務指在同一時間內執行多個任務,比如電腦同時運行微信、瀏覽器和代碼編輯器。其核心價值是充分利用 CPU 資源,提升程序執行效率。
2. 兩種表現形式
多任務的實現分為 “并發” 和 “并行”,二者的核心區別在于是否 “真正同時執行”:
(1)并發:單核 CPU 場景下,操作系統輪流讓多個任務交替執行(如任務 1 執行 0.01 秒→切換到任務 2 執行 0.01 秒)。由于 CPU 速度極快,表面上看起來任務在同時運行。適用場景:任務數量>CPU 核心數。
(2)并行:多核 CPU 場景下,每個核心分別執行一個任務,多個任務真正同時進行。適用場景:任務數量≤CPU 核心數。
二、進程:操作系統資源分配的最小單位
1. 進程的概念
進程(Process)是操作系統進行資源分配和調度的基本單位,一個正在運行的程序就是一個進程(如打開的微信、Chrome 瀏覽器)。一個程序運行后至少會創建一個主進程。
2. 多進程實現多任務
通過 Python 的multiprocessing模塊,我們可以創建子進程,讓多個任務并行執行。
核心步驟
(1)導入multiprocessing模塊;
(2)用multiprocessing.Process()創建進程對象,指定目標任務(函數名);
(3)調用start()方法啟動進程。
2.1 基礎示例:邊聽音樂邊敲代碼
import multiprocessing
import time# 任務1:聽音樂
def music():for i in range(3):print("聽音樂...")time.sleep(0.2)# 任務2:敲代碼
def coding():for i in range(3):print("敲代碼...")time.sleep(0.2)if __name__ == '__main__':# 創建進程對象music_process = multiprocessing.Process(target=music)coding_process = multiprocessing.Process(target=coding)# 啟動進程music_process.start()coding_process.start()
2.2 帶參數的進程任務
通過args(元組)或kwargs(字典)給任務傳遞參數:
if __name__ == '__main__':# 元組傳參(注意逗號)music_process = multiprocessing.Process(target=music, args=(3,))# 字典傳參coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})music_process.start()coding_process.start()
2.3 進程編號與應用注意點
2.3.1 進程編號的作用
每個進程都有唯一編號(PID),用于區分主進程和子進程,方便進程管理。通過os
模塊獲取:
(1)os.getpid():獲取當前進程編號;
(2)os.getppid():獲取父進程編號(創建當前進程的進程)
。
2.3.2 關鍵注意點
(1)進程間不共享全局變量:子進程會拷貝主進程的資源,修改子進程的全局變量不會影響主進程;
(2)主進程與子進程的結束順序:默認主進程會等待所有子進程執行完再結束。若需主進程結束時子進程也終止,可:
- 設置守護進程:process.daemon = True;
- 手動終止子進程:process.terminate()。
三、線程:程序執行的最小單位
1. 線程的概念
線程(Thread)是進程內的執行單元,共享進程的所有資源(如內存、文件句柄)。一個進程默認有一個主線程,可創建多個子線程,就像 “一個 QQ 打開兩個聊天窗口”,既實現多任務又節省資源。
2. 多線程實現多任務
通過threading
模塊實現,步驟與多進程類似,且資源開銷更低、啟動速度更快。
基礎示例
import threading
import timedef music():for i in range(3):print("聽音樂...")time.sleep(0.2)def coding():for i in range(3):print("敲代碼...")time.sleep(0.2)if __name__ == '__main__':# 創建線程對象music_thread = threading.Thread(target=music)coding_thread = threading.Thread(target=coding)# 啟動線程music_thread.start()coding_thread.start()
3. 線程的核心特性
- 共享全局變量:同一進程內的線程共享全局變量(如列表、字典),但需注意 “線程安全”(需用鎖避免數據競爭);
- 執行順序無序:線程的執行由 CPU 調度決定,無法保證順序;
- 守護線程:設置
thread.daemon = True
,主線程結束時子線程自動終止。
四、進程與線程的對比
特性 | 進程(Process) | 線程(Thread) |
---|---|---|
定義 | 資源分配最小單位 | 程序執行最小單位 |
資源開銷 | 高(獨立內存、資源) | 低(共享進程資源) |
啟動速度 | 慢 | 快 |
全局變量共享 | 不共享(需 IPC 通信) | 共享(需鎖保證安全) |
適用場景 | CPU 密集型任務(如計算、數據分析) | I/O 密集型任務(如網絡請求、文件讀寫) |
模塊 | multiprocessing | threading |
五、協程:用戶態的輕量級線程
1. 協程的概念
協程(Coroutine)是用戶態的輕量級線程,通過 “協作式調度” 實現并發 —— 無需操作系統介入,僅需保存寄存器上下文,切換效率極高。
2. 核心優勢
- 無鎖機制:避免多線程的同步開銷;
- 高并發:單線程內可處理數千個 I/O 密集型任務;
- 代碼簡潔:用
async/await
語法,以同步風格寫異步邏輯。
3. 基于asyncio實現協程
asyncio是 Python 官方協程庫,核心是 “事件循環”(管理協程的執行)。
基礎示例
import asyncio# 定義協程函數(用async修飾)
async def my_coroutine():print("Start")# 非阻塞等待(替代time.sleep,不阻塞事件循環)await asyncio.sleep(1)print("End")# 啟動事件循環
asyncio.run(my_coroutine())
并發執行多個協程
用asyncio.create_task()創建任務,asyncio.gather()并發執行:
async def task(name, delay):await asyncio.sleep(delay)print(f"{name} completed")async def main():# 創建任務列表tasks = [asyncio.create_task(task("A", 2)),asyncio.create_task(task("B", 1))]# 并發執行await asyncio.gather(*tasks)asyncio.run(main())
# 輸出:B completed → A completed(按完成時間排序)
4. 協程的適用場景與注意事項
- 適用場景:I/O 密集型任務(如網絡爬蟲、API 調用),結合aiohttp(異步 HTTP 庫)可大幅提升效率;
- 注意事項:
(1)協程內禁用time.sleep()等同步操作,需用asyncio.sleep();
(2)需 Python 3.7+,推薦用asyncio.run()管理事件循環。
(3)不適合 CPU 密集型任務(需結合多進程);
六、總結:如何選擇多任務方案
- CPU 密集型任務(如計算、矩陣運算):用多進程(繞過 Python GIL 鎖,利用多核 CPU);
- I/O 密集型任務(如網絡請求、文件讀寫):優先用協程(效率最高、資源開銷最低),其次用多線程;
- 簡單多任務場景:若無需多核利用,用多線程(實現簡單、通信方便)。