线程(Thread)
线程是操作系统调度的最小单位,线程通常在一个进程内创建和执行。多个线程可以共享进程的内存空间和资源。线程适合于 I/O 密集型任务(如文件操作、网络请求等),但由于 Python 的全局解释器锁(GIL),它对于 CPU 密集型任务并没有显著的性能提升。
使用 threading 模块创建线程
Python 提供了 threading 模块来支持多线程操作。线程可以通过继承 Thread 类或使用 threading.Thread 类来创建。
import threading
import time
# 定义一个线程要执行的任务
def print_numbers():
for i in range(5):
print(f"线程打印:{i}")
time.sleep(1)
# 创建一个线程
thread = threading.Thread(target=print_numbers)
# 启动线程
thread.start()
# 等待线程结束
thread.join()
print("主程序结束")
- threading.Thread(target=…):创建一个线程对象,target 参数是线程执行的函数。
- start():启动线程,使其开始执行 target 函数。
- join():主线程会阻塞直到子线程执行完毕,确保主线程等待子线程完成。
线程中的全局解释器锁(GIL)
Python 中的全局解释器锁(GIL)确保在任何时刻只有一个线程能够执行 Python 字节码,这意味着 CPU 密集型任务在多线程中不会获得性能提升。然而,对于 I/O 密集型任务,线程依然能够提高效率,因为它们在等待 I/O 操作时可以切换到其他任务。
进程(Process)
进程是操作系统分配资源(如内存)的最小单位。每个进程都有自己独立的内存空间,因此进程之间不会共享内存。在 Python 中,进程适合于 CPU 密集型任务,因为每个进程可以独立运行,不受 GIL 的限制。Python 提供了 multiprocessing 模块来创建和管理多进程。
使用 multiprocessing 模块创建进程
import multiprocessing
import time
# 定义一个进程要执行的任务
def print_numbers():
for i in range(5):
print(f"进程打印:{i}")
time.sleep(1)
# 创建一个进程
process = multiprocessing.Process(target=print_numbers)
# 启动进程
process.start()
# 等待进程结束
process.join()
print("主程序结束")
- multiprocessing.Process(target=…):创建一个进程对象,target 参数是进程执行的函数。
- start():启动进程,使其开始执行 target 函数。
- join():主进程会阻塞直到子进程执行完毕,确保主进程等待子进程完成。
进程和线程的区别:
- 内存隔离:进程有自己独立的内存空间,而线程共享进程内的内存。
- 性能:由于进程之间没有共享内存空间,进程适合于 CPU 密集型任务,而线程更适合于 I/O 密集型任务。
- 创建和销毁成本:创建和销毁进程的成本通常比线程更高,因为进程需要独立的内存空间。
线程与进程的对比
特性 | 线程 | 进程 |
---|---|---|
内存空间 | 共享内存,线程之间可以访问相同的内存空间 | 每个进程都有独立的内存空间 |
适用场景 | I/O 密集型任务(如网络请求、文件操作等) | CPU 密集型任务(如复杂计算、数据处理等) |
性能 | 受限于 GIL(对 CPU 密集型任务有影响) | 每个进程独立运行,不受 GIL 限制 |
创建销毁成本 | 较低,线程之间的切换更为高效 | 较高,进程之间的切换需要较大的开销 |
并发模型 | 基于线程,使用全局解释器锁(GIL) | 基于进程,独立的内存空间 |
- 线程适合于 I/O 密集型任务:例如,网络请求、文件读取等,线程可以在等待 I/O 操作时切换任务。
- 进程适合于 CPU 密集型任务:例如,数据计算、图像处理等,进程可以绕过 GIL,并充分利用多核 CPU。