Python在进程之间共享锁

发布于 2021-01-29 15:08:41

我正在尝试使用部分函数,​​以便pool.map()可以定位具有多个参数(在本例中为Lock()对象)的函数。

这是示例代码(摘自我之前的问题的答案):

from functools import partial

def target(lock, iterable_item):
    for item in items:
        # Do cool stuff
        if (... some condition here ...):
            lock.acquire()
            # Write to stdout or logfile, etc.
            lock.release()

def main():
    iterable = [1, 2, 3, 4, 5]
    pool = multiprocessing.Pool()
    l = multiprocessing.Lock()
    func = partial(target, l)
    pool.map(func, iterable)
    pool.close()
    pool.join()

但是,当我运行此代码时,出现错误:

Runtime Error: Lock objects should only be shared between processes through inheritance.

我在这里想念什么?如何在子流程之间共享锁?

关注者
0
被浏览
105
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您不能将普通multiprocessing.Lock对象传递给Pool方法,因为它们不能被腌制。有两种方法可以解决此问题。一种是创建Manager()并传递一个Manager.Lock()

    def main():
        iterable = [1, 2, 3, 4, 5]
        pool = multiprocessing.Pool()
        m = multiprocessing.Manager()
        l = m.Lock()
        func = partial(target, l)
        pool.map(func, iterable)
        pool.close()
        pool.join()
    

    不过,这有点重量级;使用Manager需要产生另一个进程来托管Manager服务器。并且所有对acquire/release锁的调用都必须通过IPC发送到该服务器。

    另一种选择是multiprocessing.Lock()使用initializerkwarg在创建池时传递常规值。这将使您的锁实例在所有子工作者中都是全局的:

    def target(iterable_item):
        for item in items:
            # Do cool stuff
            if (... some condition here ...):
                lock.acquire()
                # Write to stdout or logfile, etc.
                lock.release()
    def init(l):
        global lock
        lock = l
    
    def main():
        iterable = [1, 2, 3, 4, 5]
        l = multiprocessing.Lock()
        pool = multiprocessing.Pool(initializer=init, initargs=(l,))
        pool.map(target, iterable)
        pool.close()
        pool.join()
    

    第二种解决方案具有不再需要的副作用partial



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看