如何使用Python多处理创建同步对象?

如何使用Python多处理创建同步对象?,python,synchronization,thread-safety,multiprocessing,Python,Synchronization,Thread Safety,Multiprocessing,我很难弄清楚如何创建同步Python对象。我有一个名为Observation的类和一个名为Variable的类,基本上看起来像(代码被简化以显示本质): 以下是我设置多处理部件的方式: plugin=在其他地方定义的函数 任务=JoinableQueue() 结果=JoinableQueue() 经理=经理() lock=mgr.RLock() var=变量('foobar','year',lock) 代码应该如何工作的示例: 我有一个名为var的变量实例,我想向var添加一个观察值: toda

我很难弄清楚如何创建同步Python对象。我有一个名为Observation的类和一个名为Variable的类,基本上看起来像(代码被简化以显示本质):

以下是我设置多处理部件的方式: plugin=在其他地方定义的函数 任务=JoinableQueue() 结果=JoinableQueue() 经理=经理() lock=mgr.RLock() var=变量('foobar','year',lock)

代码应该如何工作的示例:

我有一个名为var的变量实例,我想向var添加一个观察值:

today = datetime.datetime.today()  
var.add(today, 1)  
因此,Variable的add函数查看是否已经存在该日期的观测值,如果已经存在,则返回该观测值,否则将创建一个新的观测值实例。发现比实际值大的观测值后,通过调用obs.add(value)进行添加。我主要关心的是,我想确保不同的流程不会为同一个日期创建多个观察实例,这就是我锁定它的原因

创建变量的一个实例,并使用多处理库在不同进程之间共享,它是多个观察实例的容器。上面的代码不起作用,我得到错误:

RuntimeError:锁定对象只应 通过在流程之间共享 继承权

然而,如果我在启动不同进程之前实例化一个锁对象,并将其提供给变量的构造函数,那么我似乎得到了一个竞争条件,因为所有进程似乎都在等待对方

最终目标是不同的进程可以更新对象变量中的obs变量。我需要这是线程安全的,因为我不仅仅是修改字典,而是添加新元素和增加现有变量。obs变量是一个字典,其中包含一组观察实例

在多个多处理进程之间共享一个变量实例的情况下,如何使其同步?非常感谢您的认知盈余

更新1:
*我正在使用多处理锁,我已更改源代码以显示这一点。
*为了更准确地捕捉问题,我已更改了标题
*我已经用同步取代了ADSAFE,因为我混淆了这两个术语

感谢Dmitry Dvoinikov指出我的观点

我仍然不确定的一个问题是在哪里实例化锁?这应该发生在类内部还是在初始化多进程并将其作为参数提供之前?答:应该发生在课外

更新2:
*通过将锁的初始化移到类定义之外并使用管理器,我修复了“锁对象只能通过继承在进程之间共享”错误。
*最后一个问题,现在一切都正常了,只是当我把变量实例放在队列中时,它似乎没有得到更新,而且每次我从队列中得到它时,它都不包含我在上一次迭代中添加的观察结果。这是唯一让我困惑的事情:(

更新3:

最后的解决方案是将var.obs字典设置为mgr.dict()的实例然后有一个自定义序列化程序。很高兴能与正在为此而挣扎的人共享代码。

您谈论的不是线程安全,而是独立进程之间的同步,这是完全不同的事情。无论如何,开始吧

不同的进程可以更新对象变量中的obs变量

意味着变量在共享内存中,您必须显式地将对象存储在共享内存中,而本地实例对于单独的进程来说是可见的。这里:

数据可以使用值或数组存储在共享内存映射中

然后,您的代码段缺少关键的导入部分。无法判断您是否实例化了正确的multiprocessing.Lock,而不是multithreading.Lock。您的代码没有显示创建进程和传递数据的方式


因此,我建议您认识到线程和进程之间的区别,是否真的需要一个包含多个进程的应用程序的共享内存模型,并检查它。

嗨,Dimitry,谢谢您的回答!我根据您的反馈改进了这个问题。我知道线程和pro之间的区别访问,但我已经澄清了导入部分。我仍在为在何处实例化锁而苦苦挣扎?这应该发生在类内部还是在初始化多进程并将其作为变量和观察的参数之前?是的,变量应该使用共享内存。没有必要使任何类的实例“安全”以任何特殊的方式,因为在多处理场景中,来自不同进程的线程可能不会执行来自它的代码。您在进程之间共享的只是简单的哑数据值。换句话说,锁不应该保护某个实例的内部,而应该保护对外部值的访问,即您只能同步对其的访问共享数据。至于何时初始化锁,据我所知,锁需要由主进程创建,并作为参数传递给从进程。你是对的,锁的初始化需要在类之外进行。除了在队列上进行迭代时,我得到一个新任务,然后新任务中的变量实例就好像刚刚初始化一样,它不包含以前添加的任何观察结果……从听起来,队列是将值从A点传递到B点,而不是累积任何内容。如果从进程推送某个内容,则主进程会原封不动地将其弹出(并更新它可能具有的任何统计信息)。您确定选择了正确的值吗
for person in persons:
    tasks.put(Task(plugin, var, person))
today = datetime.datetime.today()  
var.add(today, 1)