目录
一,什么是多线程多进程
1,1 多线程
1.2 多进程
二,多线程
2.1 使用threading模块
三,多进程
3.1 使用multiprocessing模块
3.2 多进程的优势
3.3 进程间的通信
四,如何选择多进程还是多线程
五,异步编程的替代方案(协程)
在开发过程中,提升程序的并发性能是开发者常常面临的挑战。为此,Python 提供了多线程和多进程两种并发编程方式,来帮助我们充分利用系统资源,提高程序的执行效率。
一,什么是多线程多进程
1,1 多线程
1. 多线程(Multithreading)
线程是进程中的一个执行单元。一个进程可以包含多个线程,它们共享同一个内存空间,共同完成任务。在 Python 中,多线程通常用于 I/O 密集型任务(例如网络请求、文件读写等),因为这些任务往往会因为 I/O 操作而被阻塞。通过多线程,我们可以让程序在等待 I/O 操作时继续处理其他任务,从而提升程序的整体响应速度。
1.2 多进程
进程是操作系统中资源分配的最小单位,每个进程有自己独立的内存空间。多进程意味着同时运行多个进程,它们之间互不干扰,互相独立。多进程更适合 CPU 密集型任务(如大规模数据计算、图像处理等),因为 Python 的全局解释器锁(GIL)限制了多线程在多核 CPU 上的性能发挥,而多进程可以有效利用多个 CPU 核心来并行处理任务。
二,多线程
Python 提供了 threading
模块来创建和管理多线程。下面是一个简单的多线程示例:
2.1 使用threading模块
import threading
import timedef worker(n):print(f"Thread {n} started")time.sleep(2)print(f"Thread {n} finished")# 创建多个线程
threads = []
for i in range(5):thread = threading.Thread(target=worker, args=(i,))threads.append(thread)thread.start()# 等待所有线程结束
for thread in threads:thread.join()print("All threads finished")
示例中,我们创建了 5 个线程,每个线程都会执行 worker
函数。程序在所有线程执行完毕后才会继续往下执行。但是在python多线程中, 由于 Python 的全局解释器锁(GIL),多线程是伪的多线程,只是感觉多个任务在同时执行,Python 多线程在 CPU 密集型任务中无法充分利用多核 CPU 的优势。GIL 使得在任一时刻只有一个线程能执行 Python 字节码,这意味着多线程在处理 CPU 密集型任务时,并不会带来性能上的提升。因此,多线程适合用于 I/O 密集型任务,如网络请求、文件读写等,而不适合用于需要大量计算的 CPU 密集型任务。
三,多进程
Python 的 multiprocessing
模块允许我们通过多进程的方式执行并发任务。与多线程不同,多进程中的每个进程都有独立的内存空间,这使得它在 CPU 密集型任务中能够充分利用多核 CPU 的优势。
3.1 使用multiprocessing模块
import multiprocessing
import timedef worker(n):print(f"Process {n} started")time.sleep(2)print(f"Process {n} finished")if __name__ == '__main__':# 创建多个进程processes = []for i in range(5):process = multiprocessing.Process(target=worker, args=(i,))processes.append(process)process.start()# 等待所有进程结束for process in processes:process.join()print("All processes finished")
我们使用 multiprocessing.Process
来创建独立的进程。每个进程都会执行 worker
函数,并且彼此之间不会共享内存,独立运行。
3.2 多进程的优势
由于每个进程都有独立的内存空间,因此多进程可以充分利用多核 CPU 的优势。在处理 CPU 密集型任务时,多进程通常会比多线程带来更好的性能提升。此外,多进程不会受到 GIL 的限制,适合需要并行处理大量计算的场景。
3.3 进程间的通信
尽管多进程有独立的内存空间,有时我们仍需要在进程间共享数据。Python 提供了多种方式来实现进程间通信(IPC),例如使用 Queue
、Pipe
等。
一个简单的进程间通信示例:
例子中,我们使用 Queue
实现了父进程和子进程之间的数据通信。
from multiprocessing import Process, Queuedef worker(q):q.put("Hello from the worker process")if __name__ == '__main__':q = Queue()p = Process(target=worker, args=(q,))p.start()print(q.get()) # 从队列中获取数据p.join()
四,如何选择多进程还是多线程
选择多线程还是多进程取决于你需要解决的任务类型:
I/O 密集型任务(如网络请求、文件读写):多线程通常更合适,因为它可以有效地隐藏 I/O 等待时间,提高并发效率。
CPU 密集型任务(如复杂计算、大规模数据处理):多进程更合适,因为它能有效利用多核 CPU 资源,并且避免了 GIL 的限制。
五,异步编程的替代方案(协程)
在某些场景下,除了多线程和多进程之外,Python 还提供了异步编程的方式来处理并发任务。asyncio
是 Python 内置的异步 I/O 框架,它能够帮助开发者在处理大量 I/O 操作时进一步提升性能。异步编程通过事件循环来管理任务的调度,是多线程的一种轻量级替代方案。线程是由系统来调度的,协程可以由开发来控制调度,协程就比线程更加的灵活,可看下篇文章python之协程