多进程编程
基本概念
多进程(multiprocessing)是指同时运行多个进程的程序设计方式。在Unix/Linux系统中,可以使用fork()系统调用创建子进程。
创建进程的三种方式
1. 使用os.fork()(仅Unix/Linux/macOS)
import os
pid = os.fork()
if pid == 0:
print('子进程')
else:
print('父进程')
2. 使用multiprocessing.Process
from multiprocessing import Process
import os
def run_proc(name):
print(f'子进程 {name} ({os.getpid()})')
if __name__ == '__main__':
p = Process(target=run_proc, args=('test',))
p.start()
p.join() # 等待子进程结束
3. 使用进程池Pool
from multiprocessing import Pool
import os, time
def long_time_task(name):
print(f'任务 {name} ({os.getpid()})')
time.sleep(2)
if __name__ == '__main__':
p = Pool(4) # 最多同时执行4个进程
for i in range(5):
p.apply_async(long_time_task, args=(i,))
p.close()
p.join()
进程间通信
使用Queue实现进程间数据交换:
from multiprocessing import Process, Queue
import os, time
def write(q):
for value in ['A', 'B', 'C']:
q.put(value)
time.sleep(1)
def read(q):
while True:
value = q.get(True)
print(f'获取: {value}')
if __name__ == '__main__':
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
pw.start()
pr.start()
pw.join()
pr.terminate()
多线程编程
基本使用
import threading
import time
def loop():
print(f'线程 {threading.current_thread().name} 运行中')
for i in range(5):
print(f'线程 {threading.current_thread().name} >>> {i}')
time.sleep(1)
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
线程安全与锁机制
多线程共享变量可能导致数据混乱,需要使用锁来保证线程安全:
import threading
balance = 0
lock = threading.Lock()
def change_it(n):
global balance
balance = balance + n
balance = balance - n
def run_thread(n):
for i in range(100000):
lock.acquire() # 获取锁
try:
change_it(n)
finally:
lock.release() # 释放锁
ThreadLocal:线程局部变量
import threading
local_school = threading.local()
def process_student():
std = local_school.student
print(f'Hello, {std} (in {threading.current_thread().name})')
def process_thread(name):
local_school.student = name
process_student()
进程 vs. 线程比较
优缺点对比
- 多进程 优点:稳定性高,子进程崩溃不影响主进程 缺点:创建开销大,占用资源多
- 多线程 优点:创建开销小,共享内存方便 缺点:一个线程崩溃可能导致整个进程崩溃
适用场景
- 计算密集型任务:适合用多进程,最好用C语言编写
- IO密集型任务:适合用多线程,Python是良好选择
Python的GIL限制
Python的全局解释器锁(GIL)限制了多线程无法真正利用多核CPU。要充分利用多核,应使用多进程或C扩展。
分布式进程
使用multiprocessing.managers模块可以实现分布式多进程:
服务端(task_master.py):
from multiprocessing.managers import BaseManager
import queue
task_queue = queue.Queue()
result_queue = queue.Queue()
class QueueManager(BaseManager): pass
QueueManager.register('get_task_queue', callable=lambda: task_queue)
QueueManager.register('get_result_queue', callable=lambda: result_queue)
manager = QueueManager(address=('', 5000), authkey=b'abc')
manager.start()
客户端(task_worker.py):
class QueueManager(BaseManager): pass
QueueManager.register('get_task_queue')
QueueManager.register('get_result_queue')
m = QueueManager(address=('127.0.0.1', 5000), authkey=b'abc')
m.connect()
task = m.get_task_queue()
result = m.get_result_queue()
总结
- 多进程适合CPU密集型任务,稳定性更好
- 多线程适合IO密集型任务,创建开销小
- Python有GIL限制,多线程无法利用多核
- 分布式进程可以将任务分布到多台机器执行
- 根据具体需求选择合适的并发模型