跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Python算法

Python 多任务编程:进程与线程实战指南

综述由AI生成深入解析了 Python 中的多任务编程机制,涵盖进程与线程的核心概念、创建方法及差异对比。内容详细阐述了多进程如何实现资源隔离与并行计算,以及多线程如何利用共享内存提升效率并解决数据竞争问题。通过互斥锁(Lock)的使用示例,展示了保障线程安全的具体方案。文章最后总结了两者在资源开销、稳定性及适用场景上的权衡,帮助开发者根据实际需求选择合适的并发模型。

星落发布于 2026/3/16更新于 2026/4/294 浏览
Python 多任务编程:进程与线程实战指南

多任务概述

多任务的核心优势在于充分利用 CPU 资源,从而大幅提升程序执行效率。在单任务模式下,一个函数或方法必须执行完毕,下一个才能开始;而多任务允许我们在同一时间内(或宏观上交替)执行多个任务。

操作系统层面的多任务通常有两种表现形式:

  • 并发:在一段时间内,系统交替执行多个任务,给人同时运行的感觉。
  • 并行:在一段时间内,真正的多个任务同时一起执行(通常需要多核支持)。

文章配图 文章配图

进程(Process)

基本概念

进程是 CPU 资源分配的最小单位,也是操作系统进行资源调度运行的基本实体。通俗来说,正在运行的程序就是一个进程。例如,当前打开的 QQ、微信等应用,每一个都是一个独立的进程。

注意:一个程序运行后至少包含一个进程。

为什么需要多进程?

假设有一个简单的脚本 hello.py,其中包含两个函数 func_a 和 func_b。默认情况下,代码按顺序执行:func_a 跑完才轮到 func_b。如果能让它们同时运行,程序的整体效率显然会更高。

文章配图

创建进程的步骤

在 Python 中实现多任务,主要依赖 multiprocessing 模块。

  1. 导入工具包

    import multiprocessing
    
  2. 实例化进程对象 使用 multiprocessing.Process 类创建子进程对象。关键参数如下:

    • target:子进程要执行的任务(通常是回调函数)。
    • args:以元组形式传递参数,顺序需与函数定义一致。
    • kwargs:以字典形式传递参数,key 需与函数参数名一致。
    • name:子进程的名称,便于调试。
  3. 启动进程 调用 process_object.start() 来启动任务。

代码示例:一边敲代码一边听音乐

下面是一个模拟多任务的经典案例,展示如何同时执行两个独立任务。

""" 使用多进程 模拟一边敲代码,一边听音乐 """
import multiprocessing
import time

def coding():
    for i in range(3):
        print("I'm coding")
        time.sleep(0.2)

def music():
    for i in range(3):
        print("I'm music...")
        time.sleep(0.2)

if __name__ == '__main__':
    # 通过进程类创建进程对象
    p1 = multiprocessing.Process(target=coding)
    p2 = multiprocessing.Process(target=music)
    
    # 启动进程
    p1.start()
    p2.start()

带参数的任务处理

实际开发中,任务往往需要接收参数。我们可以灵活使用 args 或 kwargs。

""" 进程带参数的任务 """
import multiprocessing
import time

def coding(num, name):
    for i in range(num):
        print(f"{name}在写第{i}行代码")
        time.sleep(0.2)

def music(num, name):
    for i in range(num):
        print(f"{name}在听第{i}首音乐")
        time.sleep(0.2)

if __name__ == '__main__':
    # args 传参:顺序必须匹配
    p1 = multiprocessing.Process(target=coding, args=(3, "小王"))
    # kwargs 传参:key 必须匹配参数名
    p2 = multiprocessing.Process(target=music, kwargs={"num": 7, "name": "大名"})
    
    p1.start()
    p2.start()

进程编号与管理

每个进程都有唯一的 ID,方便我们区分主进程和子进程,验证父子关系。

  • 获取当前进程 ID:os.getpid()
  • 获取父进程 ID:os.getppid()

文章配图 文章配图

进程间的隔离性

这是多进程与多线程最大的区别之一:进程之间不共享全局变量。

子进程实际上是父进程的副本,它会拷贝父进程的资源(包括全局变量)。因此,不同进程修改各自的全局变量互不影响。

""" 进程之间数据是相互隔离的 """
import multiprocessing
import time

my_list = []

def write_data():
    for i in range(3):
        my_list.append(i)
        print("add:", i)
    print("write_data:", my_list)

def read_data():
    print("read_data:", my_list)

if __name__ == '__main__':
    p1 = multiprocessing.Process(target=write_data)
    p2 = multiprocessing.Process(target=read_data)
    
    p1.start()
    time.sleep(1)
    p2.start()

文章配图 文章配图

主进程与子进程的等待机制

默认情况下,主进程会等待所有子进程执行完毕后才会退出。这意味着即使主逻辑已经跑完,只要子进程还在忙,程序就不会结束。

""" 默认情况下,主进程会等待子进程执行结束再结束 """
import multiprocessing
import time

def work():
    for i in range(10):
        print("work:", i)
        time.sleep(0.2)

if __name__ == '__main__':
    work_process = multiprocessing.Process(target=work)
    work_process.start()
    time.sleep(1)
    print("主进程结束")

如果不希望主进程等待,可以设置子进程为守护进程(Daemon)。当主进程退出时,守护进程会被自动销毁,不再等待其完成。

""" 不让主进程等待子进程 """
import multiprocessing
import time

def work():
    for i in range(10):
        print("work:", i)
        time.sleep(0.2)

if __name__ == '__main__':
    work_process = multiprocessing.Process(target=work)
    # 方式 1: 设置子进程为守护进程 (推荐)
    work_process.daemon = True
    work_process.start()
    time.sleep(1)
    # 方式 2: 强制关闭子进程 (可能导致资源未释放)
    # work_process.terminate()
    print("主进程结束")

文章配图

线程(Thread)

基本概念

线程是 CPU 调度的基本单位。一个进程可以包含多个线程,线程依附于进程存在。相比进程,线程的创建和切换开销更小。

创建线程的步骤

使用 threading 模块。

  1. 导入模块:import threading
  2. 创建线程对象:threading.Thread(target=..., args=..., kwargs=...)
  3. 启动线程:thread_obj.start()

代码示例:多线程多任务

同样用'写代码 + 听音乐'的例子对比多线程的效果。

""" 多线程的使用 """
import threading
import time

def coding():
    for i in range(3):
        print("I'm coding")
        time.sleep(0.2)

def music():
    for i in range(3):
        print("I'm music...")
        time.sleep(0.2)

if __name__ == '__main__':
    coding_thread = threading.Thread(target=coding)
    music_thread = threading.Thread(target=music)
    
    coding_thread.start()
    music_thread.start()

文章配图

线程的参数传递

与进程类似,线程也支持 args 和 kwargs 传参。

""" 线程带参数的任务 """
import threading
import time

def coding(name, num):
    for i in range(num):
        print(f"{name}正在编写第{i}行代码")
        time.sleep(0.2)

def music(name, num):
    for i in range(num):
        print(f"{name}正在听第{i}首音乐")
        time.sleep(0.2)

if __name__ == '__main__':
    coding_thread = threading.Thread(target=coding, args=("小王", 3))
    music_thread = threading.Thread(target=music, kwargs={"name": "大大大", "num": 6})
    
    coding_thread.start()
    music_thread.start()

线程的执行特性

  1. 无序性:线程的执行顺序由操作系统调度决定,具有随机性。CPU 采用时间片轮转或抢占式调度,哪个线程抢到时间片就执行哪个。

  2. 共享全局变量:同一进程内的线程共享全局变量。这虽然提高了通信效率,但也带来了数据竞争问题。

""" 线程之间共享全局变量 """
my_list = []

def write_data():
    for i in range(3):
        my_list.append(i)
        print("add:", i)
    print("write_data:", my_list)

def read_data():
    print("read_data:", my_list)

if __name__ == '__main__':
    t1 = threading.Thread(target=write_data)
    t2 = threading.Thread(target=read_data)
    t1.start()
    time.sleep(1)
    t2.start()

文章配图

线程安全问题与锁

当多个线程同时修改同一个全局变量时,可能会出现数据不一致。例如两个线程同时对计数器加 1,理论上结果应为 2,但实际可能只加了 1。

原因分析:

  • 线程 t1 读取值 0。
  • 系统调度切换到 t2,t2 也读取到 0。
  • t1 计算后写回 1。
  • t2 计算后写回 1。
  • 最终结果为 1,丢失了一次更新。

解决方案:互斥锁(Lock) 通过锁机制,保证同一时刻只有一个线程能操作共享数据。

  • 流程:创建锁 -> 上锁 (acquire) -> 执行代码 -> 释放锁 (release)。
  • 死锁风险:如果忘记释放锁,或者嵌套锁处理不当,会导致程序卡死。
""" 线程之间共享全局变量可能会出现安全问题 """
import threading

my_count = 0
# 创建锁
lock = threading.Lock()

def write_data1():
    global my_count
    lock.acquire()  # 获取锁
    for i in range(1000000):
        my_count += 1
    lock.release()  # 释放锁

def write_data2():
    global my_count
    lock.acquire()  # 获取锁
    for i in range(1000000):
        my_count += 1
    lock.release()  # 释放锁

if __name__ == '__main__':
    t1 = threading.Thread(target=write_data1)
    t2 = threading.Thread(target=write_data2)
    t1.start()
    t2.start()

文章配图

守护线程

与进程类似,线程也可以设置为守护模式。主线程退出时,守护线程会自动终止。

""" 设置守护线程 """
import threading
import time

def work():
    for i in range(10):
        print("working")
        time.sleep(0.2)

if __name__ == '__main__':
    # 方式 1: 创建时设置 daemon=True
    t = threading.Thread(target=work, daemon=True)
    # 方式 2: 创建后设置
    # t.setDaemon(True)
    
    t.start()
    time.sleep(1)
    print("主进程结束")

文章配图

进程与线程对比

关系

  • 线程依附于进程,没有进程就没有线程。
  • 一个进程默认至少有一条线程,但可以创建多条。

文章配图

核心区别

特性进程线程
资源分配操作系统资源分配的基本单位CPU 调度的基本单位
内存空间进程间不共享全局变量(隔离)线程间共享全局变量
开销创建和切换开销大创建和切换开销小
稳定性Python 中多进程稳定性更强易受 GIL 限制,需注意同步

文章配图

优缺点总结

  • 进程:优点是可以利用多核 CPU 并行计算;缺点是资源消耗大,通信复杂。
  • 线程:优点是轻量级,通信方便;缺点是不能真正利用多核(受 GIL 影响),且存在数据竞争风险。

目录

  1. 多任务概述
  2. 进程(Process)
  3. 基本概念
  4. 为什么需要多进程?
  5. 创建进程的步骤
  6. 代码示例:一边敲代码一边听音乐
  7. 带参数的任务处理
  8. 进程编号与管理
  9. 进程间的隔离性
  10. 主进程与子进程的等待机制
  11. 线程(Thread)
  12. 基本概念
  13. 创建线程的步骤
  14. 代码示例:多线程多任务
  15. 线程的参数传递
  16. 线程的执行特性
  17. 线程安全问题与锁
  18. 创建锁
  19. 守护线程
  20. 进程与线程对比
  21. 关系
  22. 核心区别
  23. 优缺点总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 第十三届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组题解
  • 前端 CI/CD 流程与自动化部署实践
  • CVE-2025-64446 漏洞预警:FortiWeb 身份绕过与路径遍历复合攻击分析
  • HDFS 常用命令与 Java API 编程实践
  • Stable Diffusion 结合 AI 监控:智能安防原型搭建实战
  • JavaScript 二维码跨平台处理实战技巧与优化
  • Kiro AI 助手:核心功能与实战指南
  • 多模态 Agent 图像识别技能开发实战:JS 与 Python 全栈方案
  • VR 大空间项目内容规划与设计市场经验总结(2023-2026)
  • Linux 进程优先级与 O(1) 调度算法解析
  • Stack-Chan 机器人快速入门与配置指南
  • VS Code + GitHub Copilot 避坑指南:从安装配置到最佳实践
  • Stable Diffusion 完整训练与推理流程详解(含伪代码)
  • Stable Diffusion 完整训练与推理流程详解
  • MVEL 表达式编译与执行测试
  • GitHub 学生认证与 PyCharm 配置 Copilot 全流程指南
  • MySQL 8.0.37 离线部署指南:CentOS 7.9 本地下载与安装配置
  • 波士顿动力机器人技术解析:从 Spot 到 Atlas
  • OpenClaw 本地部署与 Ollama 集成配置指南
  • nanobot 轻量级 AI Agent 框架实战:搭建 QQ 机器人与搜索扩展

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online