Python:在生成的进程之间共享锁

Zil0

最终目标是在后台执行一个方法,而不是并行执行:当多个对象调用此方法时,每个对象都应等待其执行。为了实现在后台运行,我必须在子进程(不是线程)中运行该方法,并且需要使用spawn(而不是fork)来启动它。为了防止并行执行,显而易见的解决方案是在进程之间共享全局锁。
如以下两个代码中突出显示的那样,当分叉进程时(这是Unix上的默认设置),很容易实现。
我们可以将其作为类变量共享:

import multiprocessing as mp
from time import sleep

class OneAtATime:

    l = mp.Lock()

    def f(self):
        with self.l:
            sleep(1)
        print("Hello")

if __name__ == "__main__":
    a = OneAtATime()
    b = OneAtATime()
    p1 = mp.Process(target = a.f)
    p2 = mp.Process(target = b.f)
    p1.start()
    p2.start()

或者我们可以将其传递给方法:

import multiprocessing as mp
from time import sleep

class OneAtATime:
    def f(self, l):
        with l:
            sleep(1)
        print("Hello")

if __name__ == "__main__":
    a = OneAtATime()
    b = OneAtATime()
    m = mp.Manager()
    l = mp.Lock()
    p1 = mp.Process(target = a.f, args = (l,))
    p2 = mp.Process(target = b.f, args = (l,))
    p1.start()
    p2.start()

这两个代码都具有每隔一秒打印一次“ hello”的适当行为。但是,将start方法更改为“ spawn”时,它们会损坏。
第一个(1)同时打印两个“ hello”。这是因为类的内部状态没有被酸洗,因此它们没有相同的锁。
第二个(2)在运行时失败,并出现FileNotFoundError。我认为这与不能腌制锁的事实有关:请参阅Python在进程之间共享锁
在此答案中,提出了两个修复程序(注意:我不能使用池,因为我想随机创建任意数量的进程)。
我还没有找到适应第二种修复方法的方法,但是我尝试实现第一种:

import multiprocessing as mp
from time import sleep

if __name__ == "__main__":
    mp.set_start_method('spawn')

class OneAtATime:
    def f(self, l):
        with l:
            sleep(1)
        print("Hello")

if __name__ == "__main__":
    a = OneAtATime()
    b = OneAtATime()
    m = mp.Manager()
    l = m.Lock()
    p1 = mp.Process(target = a.f, args = (l,))
    p2 = mp.Process(target = b.f, args = (l,))
    p1.start()
    p2.start()

这将因AttributeError和FileNotFoundError(3)而失败。实际上,当使用fork方法(4)时,它也会失败(BrokenPipe)。
在产生的进程之间共享锁的正确方法是什么?
快速解释一下我所编号的四个失败也是很好的。我在Archlinux下运行Python 3.6。

Zil0

如果脚本不会过早退出,则最后一个代码段有效。加入流程就足够了:

import multiprocessing as mp
from time import sleep

class OneAtATime:
    def f(self, l):
        with l:
            sleep(1)
        print("Hello")

if __name__ == "__main__":
    mp.set_start_method('spawn')
    a = OneAtATime()
    b = OneAtATime()
    m = mp.Manager()
    l = m.Lock()
    p1 = mp.Process(target = a.f, args = (l,))
    p2 = mp.Process(target = b.f, args = (l,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

有关导致此错误的更多信息,请参见https://stackoverflow.com/a/25456494/8194503

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章