Python中Semaphore实现互斥异常,数组未正确填充求排查
问题根源与解决方案
嘿,我来帮你搞明白为啥会出现这个结果!你遇到的核心问题其实是Python多进程的内存隔离特性,这也是很多刚接触多进程的开发者容易踩的坑。
为啥结果不对?
Python的多进程中,每个子进程在启动时会复制父进程的内存空间——也就是说你定义的array和n,在proc1和proc2里都是各自独立的副本,根本不是同一个东西!
举个直白的例子:
- 父进程里的
n初始是0,proc1启动后拿到自己专属的n=0,存完array[0]=0后把自己的n改成1;proc2启动时拿到的也是自己的n=0,存array[0]=0,但它修改的是自己的array副本,父进程完全看不到这些变化。 - 你最终打印的是父进程里的原始
array,能看到前两个值被修改纯粹是子进程复制内存时的巧合,本质上两个进程各自在操作自己的变量,信号量的互斥约束完全没作用在共享资源上。
正确的实现方式
要解决这个问题,你需要用Pythonmultiprocessing模块提供的共享内存对象,让array和n在进程间真正共享,同时用信号量保证临界区的互斥操作。
下面是修正后的代码:
import multiprocessing def worker(sem, shared_array, shared_n): # 每个进程执行5次操作,总共10次刚好填满数组 for _ in range(5): # 获取信号量,进入临界区 sem.acquire() # 读取共享的n值 current_n = shared_n.value # 给数组赋值 shared_array[current_n] = current_n # 自增共享n shared_n.value += 1 # 释放信号量,退出临界区 sem.release() if __name__ == "__main__": # 创建互斥信号量(初始值为1,保证同一时间只有一个进程进入临界区) sem = multiprocessing.Semaphore(1) # 创建共享数组:类型为int,初始长度10,默认值0 shared_array = multiprocessing.Array('i', [0]*10) # 创建共享整数n:类型为int,初始值0 shared_n = multiprocessing.Value('i', 0) # 创建两个进程,把共享对象和信号量传进去 proc1 = multiprocessing.Process(target=worker, args=(sem, shared_array, shared_n)) proc2 = multiprocessing.Process(target=worker, args=(sem, shared_array, shared_n)) proc1.start() proc2.start() proc1.join() proc2.join() # 把共享数组转成普通列表打印 print(list(shared_array)) # 会输出[0,1,2,3,4,5,6,7,8,9]
关键知识点
multiprocessing.Array和multiprocessing.Value:这两个是专门用于进程间共享内存的对象,所有子进程修改的都是同一块内存空间,父进程能实时看到变化。- 信号量的传递:必须把
Semaphore作为参数传给子进程,确保两个进程用的是同一个信号量,才能实现真正的互斥。 - 临界区操作:对共享变量的读写必须放在
sem.acquire()和sem.release()之间,避免多个进程同时修改导致的竞态条件。
如果之后你想尝试多线程(线程间内存是共享的),那普通的全局变量就可以用,但同样需要用信号量或者Lock来保证互斥哦!
内容的提问来源于stack exchange,提问作者Rizvan Ferdous
相关产品推荐
相关产品推荐

