在多处理中如何区分锁



假设您有两个用manager.list((创建的列表和两个用manager创建的锁。锁定((。如何将每个锁分配给每个列表?我做得像

lock1 = manager.Lock()
lock2 = manager.Lock()
list1 = manager.list()
list2 = manager.list()

当我想从列表中写入/读取时

lock1.acquire()
list1.pop(0)
lock1.release()
lock2.acquire()
list2.pop(0)
lock2.released()

今天我意识到没有什么能把lock1和list1联系起来。我是不是误解了这些功能?

TL;DR是的,这可能是XY问题!

如果您创建一个multiprocessing.Manager()并使用其方法创建容器基元(.list.dict(,它们将已经同步,您不需要自己处理同步基元

from multiprocessing import Manager, Process, freeze_support
def my_function(d, lst):
lst.append([x**2 for x in d.values()])
def main():
with Manager() as manager:  # context-managed SyncManager
normal_dict = {'a': 1, 'b': 2}
managed_synchronized_dict = manager.dict(normal_dict)
managed_synchronized_list = manager.list()  # used to store results
p = Process(
target=my_function,
args=(managed_synchronized_dict, managed_synchronized_list)
)
p.start()
p.join()
print(managed_synchronized_list)
if __name__ == '__main__':
freeze_support()
main()
% python3 ./test_so_66603485.py
[[1, 4]]

多处理。阵列,也是同步

BEWARE:代理对象不能直接与它们的Python集合等价物进行比较

注意:多处理中的代理类型不支持按值进行比较。例如,我们有:

>>> manager.list([1,2,3]) == [1,2,3]
False

在进行比较时,应该只使用引用对象的副本。


一些混淆可能来自同步原语的多处理文档部分,这意味着应该使用管理器来创建同步原语,而实际上管理器已经可以为进行同步

同步原语

通常,同步原语在多进程程序中不像在多线程程序中那样必要。请参阅有关线程模块的文档。

请注意,还可以通过使用管理器对象来创建同步原语——请参见管理器。

如果你只使用multiprocessing.Manager(),根据文档,它是

返回一个已启动的SyncManager对象,该对象可用于在进程之间共享对象。返回的管理器对象对应于派生的子进程,并具有创建共享对象并返回相应代理的方法。

来自SyncManager部分

它的方法为许多常用的数据类型创建并返回代理对象,以便在进程之间同步。其中包括共享列表和词典。

这意味着你可能已经拥有了你想要的大部分

  • 具有用于构建托管类型的方法的管理器对象
  • 通过代理对象进行同步

最后,从专门关于锁定对象实例的注释中总结线程

  • 没有固有的方法来判断某个命名锁是用于除元信息(如名称、注释、文档(之外的任何特定内容。。相反,它们可以自由用于您可能需要的任何同步
  • 可以制作一些有用的类/容器来管理锁和它应该同步的任何东西——一个普通的multiprocessing.Manager(SyncManager(的.list.dict可以做到这一点,还有各种其他有用的构造,如管道和队列
  • 一个锁可以用于同步任何数量的操作,但拥有更多的锁可能是一种有价值的权衡,因为它们可能会不必要地阻止对资源的访问
  • 还存在用于不同目的的各种同步原语
value = my_queue.get()  # already synchronized
if not my_lock1.acquire(timeout=5):  # False if cannot acquire
raise CustomException("failed to acquire my_lock1 after 5 seconds")
try:
with my_lock2():    # blocks until acquired
some_shared_mutable = some_container_of_mutables[-1]
some_shared_mutable = some_object_with_mutables.get()
if foo(value, some_shared_mutable):
action1(value, some_shared_mutable)
action2(value, some_other_shared_mutable)
finally:
lock2.release()

相关内容

  • 没有找到相关文章

最新更新