并发实现Floyd-Warshall时ProcessPoolExecutor加main检查仍失效,ThreadPoolExecutor正常
问题原因分析
- 你当前使用的
threading模块下的Lock、Semaphore、Condition等同步原语仅适用于同一进程内的线程同步,完全不兼容多进程场景:
多进程模式下每个子进程拥有独立的内存地址空间,主进程中创建的同步原语在传递给子进程时会被序列化拷贝,每个子进程拿到的都是独立的对象副本,无法实现跨进程的状态同步,该等待的信号永远等不到,自然会出现程序卡住无法执行完成的问题。
- 额外的序列化问题:你将实例方法
fwc.work传入ProcessPoolExecutor时,整个ConcurrentFloydWarshallUpdated实例都会被序列化传递给子进程,threading的多数同步原语本身就不支持序列化,就算没直接报错,拷贝后的副本也完全没有同步作用。
解决方案
- 第一步:将所有同步原语替换为
multiprocessing模块下的对应实现,包括multiprocessing.Lock、multiprocessing.Semaphore、multiprocessing.Condition,这类原语是专门为跨进程同步设计的。 - 第二步:调整同步原语的传递方式,不要将其作为普通实例属性存储在需要序列化传递的类中,推荐两种实现方式:
- 使用
multiprocessing.Manager创建可跨进程共享的同步对象,统一管理同步状态 - 在初始化进程池时通过
initializer参数将同步对象一次性传给所有子进程,避免反复序列化
- 使用
- 第三步:调整测试用例规模,你当前测试的顶点数
v=10计算量极小,多进程的IPC、序列化开销会远大于计算收益,至少将顶点规模提升到数百以上才能观测到多进程的性能优势。
内容的提问来源于stack exchange,提问作者SS-Salt
相关产品推荐
相关产品推荐

