Python多进程中GlobalCount全局变量无法同步问题求助
问题
我在代码里声明了全局变量GlobalCount,用multiprocessing启动process()方法每秒对它自增,断点查看自增操作正常,但并行发送GETSTATUS请求获取其值时,返回结果始终为0。请问哪里操作错误?
问题代码
import multiprocessing import socket import time from multiprocessing import Value # globals GlobalCount = Value('i', 0) # 'i' stands for integer def main(): server_ip = "127.0.0.1" server_port = 2222 # Create a UDP socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = (server_ip, server_port) server_socket.bind(server_address) response = "" print("UDP server is listening on {}:{}".format(*server_address)) while True: # Receive data from the client data, client_address = server_socket.recvfrom(256) if data: data_str = data.decode('utf-8') arrayParams = data_str.split(';') if arrayParams[0] == "PROCESS": server_socket.sendto(response.encode(), client_address) # Start the process in parallel training_process = multiprocessing.Process(target=process) training_process.start() elif arrayParams[0] == "GETSTATUS": current_value = GlobalCount.value response = str(current_value) # here GlobalCount is always 0 server_socket.sendto(response.encode(), client_address) else: print("") def process(): for i in range(100): with GlobalCount.get_lock(): # Ensure thread-safety when updating the value GlobalCount.value += 1 time.sleep(1) # Execute at start if __name__ == '__main__': main()
问题原因与解决方法
问题核心是多进程启动机制导致共享变量被重复初始化:
- 在Windows系统下,
multiprocessing.Process采用spawn方式创建子进程,会重新导入主模块。你的GlobalCount定义在模块全局作用域,子进程启动时会重新执行这行代码,生成新的Value实例——子进程修改的是自己的副本,主进程的GlobalCount始终是初始值0。 - 即便在Unix/Linux系统(用
fork机制),虽然能继承父进程变量,但将共享变量显式传入子进程是更安全、跨平台的写法。
修改步骤
- 将
GlobalCount的初始化移到main()函数内部,避免子进程重新初始化。 - 启动子进程时,将
GlobalCount作为参数传入process()函数,确保子进程操作的是同一个共享对象。
修改后的代码
import multiprocessing import socket import time from multiprocessing import Value def main(): # 将共享变量移到main内部,避免子进程重复初始化 GlobalCount = Value('i', 0) # 'i' stands for integer server_ip = "127.0.0.1" server_port = 2222 server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = (server_ip, server_port) server_socket.bind(server_address) response = "" print("UDP server is listening on {}:{}".format(*server_address)) while True: data, client_address = server_socket.recvfrom(256) if data: data_str = data.decode('utf-8') arrayParams = data_str.split(';') if arrayParams[0] == "PROCESS": server_socket.sendto(response.encode(), client_address) # 启动子进程时传入共享变量 training_process = multiprocessing.Process(target=process, args=(GlobalCount,)) training_process.start() elif arrayParams[0] == "GETSTATUS": current_value = GlobalCount.value response = str(current_value) server_socket.sendto(response.encode(), client_address) else: print("") # 修改process函数,接收传入的共享变量 def process(GlobalCount): for i in range(100): with GlobalCount.get_lock(): GlobalCount.value += 1 time.sleep(1) if __name__ == '__main__': main()
补充说明
multiprocessing.Value本身是进程安全的共享对象,但必须保证所有进程操作的是同一个实例。- 上述修改兼容Windows、Unix/Linux所有平台,避免了系统机制差异带来的问题。
内容的提问来源于stack exchange,提问作者Jaume
相关产品推荐
相关产品推荐

