You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python multiprocessing Lock未阻塞对象访问问题及解决方法

问题场景

如下代码模拟了商店场景:商店初始库存为5件商品,共有3位顾客,每位顾客需购买1件商品。

import multiprocessing as mp
 
class Shop:
    def __init__(self, stock=5):
        self.stock = stock

    def get_item(self, l, x):
        l.acquire()
        if self.stock >= x:
            self.stock -= x
            print(f"{self.stock} = remaining")
        l.release()

if __name__ == "__main__":
    l = mp.Lock()
    obj = Shop()

    p1 = mp.Process(target=obj.get_item, args=(l, 1))
    p2 = mp.Process(target=obj.get_item, args=(l, 1))
    p3 = mp.Process(target=obj.get_item, args=(l, 1))

    p1.start()
    p2.start()
    p3.start()

    p1.join()
    p2.join()
    p3.join()

    print("Final: ", obj.stock)

实际运行输出

4 = remaining
4 = remaining
4 = remaining
Final:  5

预期输出

代码中已经使用了Lock做同步,预期得到如下输出:

4 = remaining
3 = remaining
2 = remaining
Final:  2

核心问题

如何仅使用Lock(不使用Pipe/Queue等进程通信机制)实现上述预期输出?


问题原因

原有代码失效的核心原因是多进程默认内存隔离:

  • multiprocessing创建的子进程拥有独立的地址空间,传入子进程的Shop实例会被拷贝一份,实例属性stock是每个进程私有的,子进程修改自己的副本不会影响其他子进程,也不会同步回主进程。
  • 代码中的Lock确实是跨进程生效的,但它保护的只是每个进程对自己私有stock的修改操作,完全没有解决跨进程状态共享的问题,因此才会出现三个进程都把自己的库存从5减到4、主进程库存始终为5的现象。
解决方案

Lock本身只是同步原语,不具备存储共享状态的能力,要实现跨进程状态同步,只需要把库存值放到所有进程都能访问的共享内存中,再配合现有Lock做原子操作保护即可——共享内存不属于题目禁止的Pipe/Queue类消息通信机制,完全符合要求。

修改后的可运行代码如下:

import multiprocessing as mp
 
class Shop:
    def __init__(self, stock=5):
        # 用跨进程共享的内存块存储库存,'i'对应C语言int类型
        self.stock = mp.Value('i', stock)

    def get_item(self, l, x):
        l.acquire()
        if self.stock.value >= x:
            self.stock.value -= x
            print(f"{self.stock.value} = remaining")
        l.release()

if __name__ == "__main__":
    l = mp.Lock()
    obj = Shop()

    p1 = mp.Process(target=obj.get_item, args=(l, 1))
    p2 = mp.Process(target=obj.get_item, args=(l, 1))
    p3 = mp.Process(target=obj.get_item, args=(l, 1))

    p1.start()
    p2.start()
    p3.start()

    p1.join()
    p2.join()
    p3.join()

    print("Final: ", obj.stock.value)

运行后即可得到预期输出:Lock保证同一时间只有一个进程能修改共享内存中的库存值,三个进程依次扣减库存,最终主进程读取到的共享内存库存值为2。


内容的提问来源于stack exchange,提问作者Lawhatre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:24:10