Python多进程中整数变量正确增减的实现问题与求助
多进程共享计数原子性问题的分析与解决
错误原因
- 锁未跨进程共享:你在函数内创建的
Lock()是每个进程独立的局部锁,不同进程的锁互不干扰,完全无法起到同步多进程操作共享变量的作用。 - 自增操作非原子性:
_m.value += 1本质是「读取当前值→加1→写回新值」三步操作,没有同步锁的情况下,多个进程会同时读取到相同的旧值,最终导致计数重复。
修正方案
核心是使用跨进程共享的锁,包裹共享变量的读写操作,保证同一时间只有一个进程能修改计数:
- 通过
Manager()创建共享的Lock对象,和共享计数变量一起传递给每个进程。 - 将自增操作与完成判断逻辑都放在共享锁的上下文内,避免并发读写导致的不一致。
修正后的代码
from concurrent.futures import ProcessPoolExecutor import ctypes from multiprocessing import Manager, Lock from multiprocessing.managers import ValueProxy import os def calc_number(x: int, y: int, _m: "ValueProxy", lock: Lock, total_tasks: int): """模拟计算型任务""" # 模拟计算过程 res = x**y # 使用跨进程共享锁同步操作 with lock: _m.value += 1 # 在锁内判断是否完成所有任务,保证读取的是最新值 is_all_done = _m.value == total_tasks if is_all_done: print("所有任务已完成,通知Java执行整体入库操作") print(f"m_value: {_m.value}, p_id: {os.getpid()}, res: {res}") def main(): # 8组任务数据 t1 = (100, 200, 300, 400, 500, 600, 700, 800) t2 = (80, 70, 60, 50, 40, 30, 20, 10) len_t = len(t1) # 创建共享变量与共享锁 with Manager() as manager: m = manager.Value(ctypes.c_int, 0) lock = manager.Lock() # 多进程执行任务 with ProcessPoolExecutor(max_workers=len_t) as executor: {executor.submit(calc_number, x, y, m, lock, len_t) for x, y in zip(t1, t2)} if __name__ == "__main__": main()
关键说明
- 用
manager.Lock()创建的锁是跨进程共享的,能真正限制多个进程对共享变量的并发操作。 - 将自增和完成判断逻辑放在锁内,避免出现读取到中间状态值的情况。
- 使用
Manager()上下文管理器,确保共享资源能被正确释放。
修改后m_value会依次从1递增到8,不会出现重复值,且能准确触发所有任务完成的通知逻辑。
内容的提问来源于stack exchange,提问作者Runstone
相关产品推荐
相关产品推荐

