Python多进程中threading.Lock失效问题的原因及解决方法
多进程池(multiprocessing.Pool)中锁失效的问题解决
你这段代码的问题很典型——想用锁来保证多进程下的临界区互斥,但用错了锁的类型,导致完全起不到作用。先回顾下你的代码和现象:
你的代码
import time from multiprocessing import Pool from threading import Lock import multiprocessing PROCESSES = 2 WORKER_CALLS = 2 lock = Lock() def run(num): lock.acquire() print("enter"+str(num)) time.sleep(2) print("exit" + str(num)) lock.release() if __name__ == "__main__": pool = multiprocessing.Pool(processes=PROCESSES) pool_outputs = pool.map(run, range(WORKER_CALLS)) pool.close() pool.join() print('Pool:', pool_outputs)
预期输出
enter0 exit0 enter1 exit1 Pool: [None, None]
实际输出
enter0 enter1 exit0 exit1 Pool: [None, None]
问题根源:线程锁无法跨进程生效
你用的是threading.Lock——这是线程级别的锁,它的作用范围仅限于同一个进程内部的多个线程。而multiprocessing.Pool创建的是独立的子进程,每个子进程都有自己独立的内存空间:当你在主进程中定义lock = Lock()后,每个子进程启动时会复制这个锁的副本到自己的内存里,相当于每个子进程都拿着自己的“锁”,自然无法互相约束,两个进程可以同时进入临界区。
解决方法:使用进程级锁并正确传递给子进程
要实现跨进程的互斥,你需要用multiprocessing.Lock(进程级锁),并且要通过Pool的initializer和initargs参数把锁传递给所有子进程,确保它们共享同一个锁对象(而不是各自复制副本)。
修改后的代码如下:
import time from multiprocessing import Pool, Lock import multiprocessing PROCESSES = 2 WORKER_CALLS = 2 # 定义全局变量用于子进程接收锁 global_lock = None def init_lock(lock): global global_lock global_lock = lock def run(num): global global_lock global_lock.acquire() print(f"enter{num}") time.sleep(2) print(f"exit{num}") global_lock.release() if __name__ == "__main__": lock = Lock() # 创建Pool时指定初始化函数,把锁传递给子进程 pool = multiprocessing.Pool(processes=PROCESSES, initializer=init_lock, initargs=(lock,)) pool_outputs = pool.map(run, range(WORKER_CALLS)) pool.close() pool.join() print('Pool:', pool_outputs)
关键修改点:
- 把
threading.Lock替换为multiprocessing.Lock,这是专门用于跨进程同步的锁。 - 新增
init_lock初始化函数,通过全局变量让子进程共享同一个锁对象——因为Pool的子进程启动时会执行这个初始化函数,接收主进程传递的锁实例。 - 创建Pool时指定
initializer=init_lock和initargs=(lock,),确保所有子进程拿到的是同一个锁的引用。
运行修改后的代码,就能得到你预期的输出,两个进程会依次进入临界区。
内容的提问来源于stack exchange,提问作者william007
相关产品推荐
相关产品推荐

