进程是操作系统进行资源分配和调度的基本单位 ,每个进程都有独立的内存空间 、文件描述符 和执行状态 。Python 通过 multiprocessing 模块支持多进程编程,用于充分利用多核 CPU。
一、进程 vs 线程
| 特性 | 进程 | 线程 |
|---|---|---|
| 内存空间 | 独立,互不干扰 | 共享进程的内存 |
| 数据隔离 | 天然隔离,需要 IPC | 共享数据需要加锁 |
| 创建开销 | 大(复制内存) | 小 |
| 切换开销 | 大(切换页表) | 小 |
| GIL 影响 | 无影响,真正并行 | 受 GIL 限制 |
| 适用场景 | CPU 密集型 | I/O 密集型 |
# 进程的独立内存空间
from multiprocessing import Process
data = [] # 全局列表
def worker():
data.append(1) # 每个进程有自己的 copy
print(f"进程 {id(data)}: {data}")
p1 = Process(target=worker)
p2 = Process(target=worker)
p1.start()
p2.start()
p1.join()
p2.join()
# 输出:不同进程的 data 互不影响
二、创建进程
1. 使用 Process 类
from multiprocessing import Process
import os
def worker(name, num):
print(f"进程 {name}: PID={os.getpid()}, 父进程={os.getppid()}")
return num * 2
# 方式1:直接传入函数
p = Process(target=worker, args=("worker1", 100))
p.start() # 启动进程
p.join() # 等待进程结束
# 方式2:自定义进程类
class MyProcess(Process):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print(f"运行进程: {self.name}")
p = MyProcess("my_worker")
p.start()
p.join()
2. 进程启动方式
import multiprocessing as mp
# 设置启动方式(必须在 if __name__ == '__main__' 内)
if __name__ == '__main__':
mp.set_start_method('spawn') # Windows 默认
# mp.set_start_method('fork') # Linux/macOS 默认
# 三种方式对比:
# | spawn | 全新启动,不继承父进程资源 | Windows、macOS |
# | fork | 复制父进程(不安全) | Linux |
# | forkserver | 通过服务进程 fork(安全) | Unix-like |
三、进程池(Pool)
from multiprocessing import Pool
import time
def cpu_intensive(n):
"""CPU 密集型任务"""
return sum(i * i for i in range(n))
if __name__ == '__main__':
with Pool(processes=4) as pool:
# map:阻塞,保持顺序
results = pool.map(cpu_intensive, [10**7] * 4)
print(results)
# map_async:异步非阻塞
result = pool.map_async(cpu_intensive, [10**7] * 4)
print("异步提交完成")
results = result.get() # 等待结果
# apply_async:单任务异步
async_result = pool.apply_async(cpu_intensive, (10**7,))
result = async_result.get(timeout=30)
四、进程间通信(IPC)
1. Queue(队列)
from multiprocessing import Process, Queue
def producer(q):
for i in range(5):
q.put(f"消息{i}")
print(f"生产: {i}")
q.put(None) # 结束标志
def consumer(q):
while True:
msg = q.get()
if msg is None:
break
print(f"消费: {msg}")
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q,))
p2 = Process(target=consumer, args=(q,))
p1.start()
p2.start()
p1.join()
p2.join()
2. Pipe(管道)
from multiprocessing import Process, Pipe
def worker(conn):
conn.send([1, 2, 3])
print(f"收到父进程消息: {conn.recv()}")
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=worker, args=(child_conn,))
p.start()
print(f"收到子进程数据: {parent_conn.recv()}")
parent_conn.send("来自父进程")
p.join()
3. Shared Memory(共享内存)
from multiprocessing import Process, Value, Array
def worker(val, arr):
val.value += 1
for i in range(len(arr)):
arr[i] += i
if __name__ == '__main__':
num = Value('i', 0) # 'i' 表示有符号整数
arr = Array('d', [0.0, 1.0, 2.0]) # 'd' 表示 double
processes = [Process(target=worker, args=(num, arr)) for _ in range(4)]
for p in processes:
p.start()
for p in processes:
p.join()
print(f"num: {num.value}")
print(f"arr: {arr[:]}")
4. Manager(管理器)
from multiprocessing import Process, Manager
def worker(d, l, key, value):
d[key] = value
l.append(value)
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
l = manager.list()
processes = [Process(target=worker, args=(d, l, f"key{i}", i)) for i in range(5)]
for p in processes: p.start()
for p in processes: p.join()
print(f"dict: {d}")
print(f"list: {l}")
五、进程同步(锁)
from multiprocessing import Process, Lock, Value
def worker(lock, counter):
for _ in range(1000):
with lock:
counter.value += 1
if __name__ == '__main__':
counter = Value('i', 0)
lock = Lock()
processes = [Process(target=worker, args=(lock, counter)) for _ in range(10)]
for p in processes: p.start()
for p in processes: p.join()
print(f"最终值: {counter.value}") # 应该是 10000
六、进程 vs 线程 性能对比
from multiprocessing import Process
from threading import Thread
import time
def cpu_task():
for i in range(10**7):
pass
def io_task():
time.sleep(0.1)
if __name__ == '__main__':
import time
# CPU 密集型:多进程更快(利用多核)
start = time.time()
processes = [Process(target=cpu_task) for _ in range(4)]
for p in processes: p.start()
for p in processes: p.join()
print(f"多进程CPU任务: {time.time() - start:.2f}s")
# I/O 密集型:多线程更快(切换开销小)
start = time.time()
threads = [Thread(target=io_task) for _ in range(40)]
for t in threads: t.start()
for t in threads: t.join()
print(f"多线程I/O任务: {time.time() - start:.2f}s")
结果(4核CPU):
多进程CPU任务: 1.8s # 并行利用多核
多线程CPU任务: 6.5s # 受 GIL 限制
多进程I/O任务: 0.45s # 进程开销大
多线程I/O任务: 0.12s # 线程开销小