【问题标题】:ProcessPoolExecutor and Lock in PythonPython 中的 ProcessPoolExecutor 和 Lock
【发布时间】:2016-05-25 11:28:30
【问题描述】:

我正在尝试将 concurrent.futures.ProcessPoolExecutor 与 Locks 一起使用,但我遇到了运行时错误。 (如果相关,我正在使用 Windows)

这是我的代码:

import multiprocessing
from concurrent.futures import ProcessPoolExecutor

import time


def f(i, lock):
    with lock:
        print(i, 'hello')
        time.sleep(1)
        print(i, 'world')


def main():
    lock = multiprocessing.Lock()
    pool = ProcessPoolExecutor()
    futures = [pool.submit(f, num, lock) for num in range(3)]
    for future in futures:
        future.result()


if __name__ == '__main__':
    main()

这是我得到的错误:

    Traceback (most recent call last):
  File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\queues.py", line 242, in _feed
    obj = ForkingPickler.dumps(obj)
  File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\reduction.py", line 50, in dumps
    cls(buf, protocol).dump(obj)
  File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\synchronize.py", line 102, in __getstate__
    context.assert_spawning(self)
  File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\context.py", line 347, in assert_spawning
    ' through inheritance' % type(obj).__name__
RuntimeError: Lock objects should only be shared between processes through inheritance

奇怪的是,如果我用multiprocessing.Process 编写相同的代码,一切正常:

import multiprocessing

import time


def f(i, lock):
    with lock:
        print(i, 'hello')
        time.sleep(1)
        print(i, 'world')


def main():
    lock = multiprocessing.Lock()
    processes = [multiprocessing.Process(target=f, args=(i, lock)) for i in range(3)]
    for process in processes:
        process.start()
    for process in processes:
        process.join()



if __name__ == '__main__':
    main()

这行得通,我得到:

1 hello
1 world
0 hello
0 world
2 hello
2 world

【问题讨论】:

    标签: python concurrency locking multiprocessing pool


    【解决方案1】:

    您需要使用Manager 并改用Manager.Lock()

    import multiprocessing
    from concurrent.futures import ProcessPoolExecutor
    
    import time
    
    def f(i, lock):
        with lock:
            print(i, 'hello')
            time.sleep(1)
            print(i, 'world')
    
    def main():
        pool = ProcessPoolExecutor()
        m = multiprocessing.Manager()
        lock = m.Lock()
        futures = [pool.submit(f, num, lock) for num in range(3)]
        for future in futures:
            future.result()
    
    
    if __name__ == '__main__':
        main()
    

    结果:

    % python locks.py
    0 hello
    0 world
    1 hello
    1 world
    2 hello
    2 world
    

    【讨论】:

    • 最好用Manager.Lock()解释为什么可以解决问题。
    • 这是因为Manager.Lock()可以腌制而multiprocessing.Lock()不能腌制。
    【解决方案2】:

    我试验了它按预期工作的代码。 我的理解是 Manager.Lock() 返回要获取的句柄(即 multiprocessing.managers.AcquirerProxy)。当它与关键字“with”一起使用时,它实际上锁定了除当前处理器之外的所有处理器,以便“with”范围内的代码片段充当单个处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 2023-02-25
      • 1970-01-01
      • 2020-08-09
      • 2018-06-21
      • 1970-01-01
      • 2019-11-19
      相关资源
      最近更新 更多