# 9. Python 并发与并行编程
## 多进程编程
### 概述
多进程编程是一种利用多个进程来执行任务的并发编程方式。与多线程不同,多进程可以充分利用多核 CPU 的计算能力,并且由于进程之间内存隔离,避免了全局解释器锁(GIL)的限制。Python 提供了 `multiprocessing` 模块来支持多进程编程。
### 创建进程
Python 的 `multiprocessing` 模块提供了 `Process` 类来创建和管理进程。以下是一个简单的示例:
```python
from multiprocessing import Process
def worker(name):
print(f"Process {name} is running")
if __name__ == "__main__":
processes = []
for i in range(5):
p = Process(target=worker, args=(f"Process-{i}",))
processes.append(p)
p.start()
for p in processes:
p.join()
在这个示例中,我们创建了 5 个进程,每个进程都执行 worker 函数。start() 方法启动进程,join() 方法等待进程结束。
进程间通信
由于进程之间内存隔离,进程间通信(IPC)需要通过特定的机制来实现。multiprocessing 模块提供了多种 IPC 方式,包括队列(Queue)、管道(Pipe)和共享内存(Value 和 Array)。
使用队列进行通信
队列是一种常用的进程间通信方式,支持多生产者和多消费者模型。以下是一个使用队列的示例:
from multiprocessing import Process, Queue
def producer(q):
for i in range(5):
q.put(i)
print(f"Produced {i}")
def consumer(q):
while True:
item = q.get()
if item is None:
break
print(f"Consumed {item}")
if __name__ == "__main__":
q = Queue()
p1 = Process(target=producer, args=(q,))
p2 = Process(target=consumer, args=(q,))
p1.start()
p2.start()
p1.join()
q.put(None) # 发送结束信号
p2.join()
在这个示例中,生产者进程向队列中放入数据,消费者进程从队列中取出数据。None 作为结束信号,通知消费者进程停止。
使用管道进行通信
管道是一种双向通信机制,适用于两个进程之间的通信。以下是一个使用管道的示例:
from multiprocessing import Process, Pipe
def sender(conn):
conn.send("Hello from sender")
conn.close()
def receiver(conn):
msg = conn.recv()
print(f"Received: {msg}")
conn.close()
if __name__ == "__main__":
parent_conn, child_conn = Pipe()
p1 = Process(target=sender, args=(child_conn,))
p2 = Process(target=receiver, args=(parent_conn,))
p1.start()
p2.start()
p1.join()
p2.join()
在这个示例中,Pipe 创建了两个连接对象,分别用于发送和接收数据。
进程池
multiprocessing 模块还提供了 Pool 类,用于管理多个进程的池化操作。进程池可以简化并行任务的调度和管理。以下是一个使用进程池的示例:
from multiprocessing import Pool
def square(x):
return x * x
if __name__ == "__main__":
with Pool(4) as pool:
results = pool.map(square, range(10))
print(results)
在这个示例中,Pool 创建了一个包含 4 个进程的池,map 方法将任务分配给池中的进程并行执行。
进程同步
在多进程编程中,进程之间可能需要同步操作以避免竞争条件。multiprocessing 模块提供了多种同步原语,如锁(Lock)、信号量(Semaphore)和事件(Event)。
使用锁进行同步
以下是一个使用锁的示例:
from multiprocessing import Process, Lock
def worker(lock, name):
with lock:
print(f"{name} is running")
if __name__ == "__main__":
lock = Lock()
processes = []
for i in range(5):
p = Process(target=worker, args=(lock, f"Process-{i}"))
processes.append(p)
p.start()
for p in processes:
p.join()
在这个示例中,锁确保了同一时间只有一个进程可以执行 print 语句。
总结
多进程编程是 Python 中实现并行计算的重要方式。通过 multiprocessing 模块,开发者可以轻松创建和管理多个进程,实现高效的并行任务处理。进程间通信和同步机制进一步增强了多进程编程的灵活性和可靠性。
