异步多进程实现咨询:主函数高频启动进程遇GIL阻塞问题
解决方案:用多进程替代线程解决GIL阻塞问题
Python的GIL(全局解释器锁)会限制同一时刻只有一个线程执行Python字节码,当活跃线程数量增多时,频繁的线程切换会导致执行停滞。而多进程完全不受GIL限制——每个进程拥有独立的Python解释器和内存空间,正好适配你这种需要持续启动大量长时间任务、且无需等待任务完成的场景。
方案1:直接用multiprocessing创建进程
可以直接通过multiprocessing.Process创建进程,启动后让进程在后台运行,同时用定时逻辑每5秒批量启动任务:
import multiprocessing import time def long_running_task(task_id): # 模拟耗时任务(比如5分钟) print(f"启动任务 {task_id}") time.sleep(300) print(f"任务 {task_id} 完成") def main(): task_counter = 0 while True: # 每5秒启动20个进程 for _ in range(20): task_counter += 1 p = multiprocessing.Process(target=long_running_task, args=(task_counter,)) p.start() # 启动进程,无需调用join,进程后台运行 print(f"已启动20个任务,当前任务ID到 {task_counter}") time.sleep(5) if __name__ == "__main__": main()
如果任务量极大,无限制创建进程可能耗尽系统资源,可以用multiprocessing.Pool设置最大并发进程数(比如根据CPU核心数调整):
import multiprocessing import time def long_running_task(task_id): print(f"启动任务 {task_id}") time.sleep(300) print(f"任务 {task_id} 完成") def main(): # 按CPU核心数的2倍设置最大并发进程数,避免资源过载 max_workers = multiprocessing.cpu_count() * 2 pool = multiprocessing.Pool(max_workers=max_workers) task_counter = 0 while True: for _ in range(20): task_counter += 1 # 异步提交任务,不等待结果 pool.apply_async(long_running_task, args=(task_counter,)) print(f"已提交20个任务,当前任务ID到 {task_counter}") time.sleep(5) if __name__ == "__main__": main()
方案2:用concurrent.futures.ProcessPoolExecutor(更简洁的高层封装)
ProcessPoolExecutor是对多进程的高层封装,使用起来更简洁,同样支持异步提交任务:
from concurrent.futures import ProcessPoolExecutor import multiprocessing import time def long_running_task(task_id): print(f"启动任务 {task_id}") time.sleep(300) print(f"任务 {task_id} 完成") def main(): max_workers = multiprocessing.cpu_count() * 2 with ProcessPoolExecutor(max_workers=max_workers) as executor: task_counter = 0 while True: for _ in range(20): task_counter += 1 # 提交任务后立即返回,不等待完成 executor.submit(long_running_task, task_counter) print(f"已提交20个任务,当前任务ID到 {task_counter}") time.sleep(5) if __name__ == "__main__": main()
关键注意事项
- 进程间内存不共享,如果任务需要传递数据,可使用
multiprocessing.Queue、Pipe等工具;若只是独立执行任务则无需考虑。 - 务必根据系统资源(CPU核心数、内存)设置合理的最大进程数,防止系统过载。
- 如果需要捕获任务结果或异常,可为
submit/apply_async添加回调函数,但你的场景无需等待结果,可忽略这一步。
内容的提问来源于stack exchange,提问作者Filip Lav Maksimovic
相关产品推荐
相关产品推荐

