Python中的多线程与多进程
字数 967 2025-11-03 18:01:32
Python中的多线程与多进程
知识点描述
在Python中,多线程(multithreading)和多进程(multiprocessing)是并发编程的两种核心方式,用于提升程序性能。但由于Python的全局解释器锁(GIL)限制,多线程适用于I/O密集型任务(如文件读写、网络请求),而多进程适用于CPU密集型任务(如数学计算)。理解它们的区别、适用场景及实现方法至关重要。
详细讲解步骤
-
基本概念对比
- 多线程:在同一个进程内创建多个线程,共享内存空间,但受GIL限制,同一时刻仅一个线程执行Python字节码。
- 多进程:创建多个独立进程,每个进程有独立的内存和Python解释器,可绕过GIL利用多核CPU。
- 类比:多线程像厨房里多个厨师共用一套工具(需轮流使用),多进程像多个独立厨房各用各的工具。
-
实现方法
-
多线程示例(使用
threading模块):import threading import time def task(name): print(f"线程 {name} 启动") time.sleep(2) # 模拟I/O操作 print(f"线程 {name} 结束") # 创建两个线程 t1 = threading.Thread(target=task, args=("A",)) t2 = threading.Thread(target=task, args=("B",)) t1.start() t2.start() t1.join() # 等待线程结束 t2.join() print("主线程结束")说明:
start()启动线程,join()阻塞主线程直至子线程完成。- 由于GIL,睡眠期间线程会释放锁,其他线程可运行,适合I/O等待场景。
-
多进程示例(使用
multiprocessing模块):import multiprocessing import time def cpu_intensive_task(n): total = 0 for i in range(n): total += i print(f"进程 {n} 计算结果: {total}") if __name__ == "__main__": processes = [] for i in [1000000, 2000000]: p = multiprocessing.Process(target=cpu_intensive_task, args=(i,)) processes.append(p) p.start() for p in processes: p.join() print("所有进程完成")说明:
- 每个进程独立执行,无GIL冲突,可并行计算。
- 需用
if __name__ == "__main__"保护入口,避免子进程递归创建。
-
-
关键区别与选择原则
- 数据共享:
- 多线程直接共享全局变量(需用锁避免竞争)。
- 多进程数据隔离,需通过
Queue、Pipe或共享内存通信。
- 开销:多进程创建和销毁成本更高。
- 选择标准:
- I/O密集型(如爬虫)→ 多线程(轻量级,避免CPU空转)。
- CPU密集型(如图像处理)→ 多进程(真正并行)。
- 数据共享:
-
常见问题与注意事项
- 线程安全:多线程中修改共享数据需用
Lock:lock = threading.Lock() with lock: # 修改共享变量 - 进程间通信:使用
multiprocessing.Queue:q = multiprocessing.Queue() q.put(data) # 子进程放入数据 data = q.get() # 主进程获取 - 避免全局变量:多进程中子进程不继承父进程的全局变量状态。
- 线程安全:多线程中修改共享数据需用
-
实战技巧
- 使用
concurrent.futures高级接口简化代码:# 线程池示例 from concurrent.futures import ThreadPoolExecutor with ThreadPoolExecutor() as executor: results = executor.map(task, [1, 2, 3]) - 多进程调试可用
logging模块(避免print输出混乱)。
- 使用
总结
多线程与多进程是解决并发问题的核心工具,选择取决于任务类型。理解GIL的影响、数据共享机制及资源开销,能帮助在实际场景中做出合理设计。