首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python:为什么在这里的进程之间共享多处理锁?

Python:为什么在这里的进程之间共享多处理锁?
EN

Stack Overflow用户
提问于 2017-07-11 00:32:57
回答 2查看 4.1K关注 0票数 5

我试图在进程之间共享一个锁。我理解共享锁的方法是将它作为参数传递给目标函数。然而,我发现甚至下面的方法也是有效的。我无法理解进程共享此锁的方式。有人能解释一下吗?

代码语言:javascript
运行
复制
import multiprocessing as mp
import time


class SampleClass:

    def __init__(self):
        self.lock = mp.Lock()
        self.jobs = []
        self.total_jobs = 10

    def test_run(self):
        for i in range(self.total_jobs):
            p = mp.Process(target=self.run_job, args=(i,))
            p.start()
            self.jobs.append(p)

        for p in self.jobs:
            p.join()

    def run_job(self, i):
        with self.lock:
            print('Sleeping in process {}'.format(i))
            time.sleep(5)


if __name__ == '__main__':
    t = SampleClass()
    t.test_run()
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-11 17:45:33

在Windows上(您已经说过正在使用),这类事情总是简化为关于multiprocessing如何使用pickle的详细信息,因为在Windows上跨越进程边界的所有Python数据都是通过发送端的酸洗来实现的(而在接收端则不进行筛选)。

我最好的建议是避免做引起这样的问题的事情;-)例如,在Python2下在Windows上显示的代码会爆炸,如果使用multiprocessing.Pool方法而不是multiprocessing.Process,也会在Python3下崩溃。

这不仅仅是锁,只是尝试在Python2中挑选绑定的方法(如self.run_job),想想看。您正在跨越流程边界,接收端没有对应于self的对象。self.run_job应该绑定在接收端上的对象是什么?

在Python3中,self.run_job也会对self对象的一个副本进行酸洗。这就是答案:与self相对应的self对象是在接收端通过魔术创建的。像泥一样干净。t的整个州都泡汤了,包括t.lock。这就是为什么它“起作用”。

有关更多实现细节,请参见此:

为什么我可以将实例方法传递给multiprocessing.Process,而不能传递multiprocessing.Pool?

从长远来看,如果您坚持那些显然是要工作的东西,那么您将遭受最少的神秘: pass模块--全局可调用对象(既不是实例方法,也不是本地函数),以及显式传递multiprocessing数据对象(无论是LockQueuemanager.list等的实例)。

票数 5
EN

Stack Overflow用户

发布于 2017-07-11 16:28:54

在Unix操作系统上,通过fork原语创建新进程。

fork原语的工作方式是克隆父进程内存地址空间,将其分配给子进程。子对象将拥有父内存的副本以及文件描述符和共享对象的副本。

这意味着,当您调用叉时,如果父文件已打开,子文件也将被打开。同样适用于共享对象,如管道、套接字等.

在Unix+CPython中,Locks是通过sem_open原语实现的,而sem_open原语在分叉进程时被设计为共享

我通常建议不要将并发(特别是多进程)和面向对象( OOP )混合在一起,因为它经常导致这种误解。

编辑:

刚才看到你在使用Windows。蒂姆·彼得斯给出了正确的答案。为了抽象起见,Python试图通过它的API提供与操作系统无关的行为。当调用实例方法时,它将对对象进行筛选,并通过管道发送它。从而提供了类似于Unix的行为。

我建议您阅读方案编制准则进行多处理。你的问题特别是在第一点:

避免共享状态 应尽可能避免在进程之间转移大量数据。 最好还是坚持使用队列或管道在进程之间进行通信,而不是使用低级的同步原语。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45023569

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档