Python 多任务编程:进程、线程与协程全面解析

发布于:2025-09-08 ⋅ 阅读:(21) ⋅ 点赞:(0)

目录

一、多任务基础:并发与并行

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 time

def 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 密集型任务(需结合多进程);

六、总结:如何选择多任务方案

  1. CPU 密集型任务(如计算、矩阵运算):用多进程(绕过 Python GIL 锁,利用多核 CPU);
  2. I/O 密集型任务(如网络请求、文件读写):优先用协程(效率最高、资源开销最低),其次用多线程;
  3. 简单多任务场景:若无需多核利用,用多线程(实现简单、通信方便)。

网站公告

今日签到

点亮在社区的每一天
去签到