如何正确使用SyncManager.Lock或Event? [英] How to use SyncManager.Lock or Event correctly?
问题描述
我在正确使用SyncManager.Lock
时遇到了麻烦.我阅读了官方文档,但是没有提供有效的示例.我也不知道如何正确使用SyncManager.Event
.
I'm having trouble using SyncManager.Lock
correctly. I read the official doc, but it offers no working example. I also have no idea how to use SyncManager.Event
correctly.
下面是说明我的问题的最小代码. client1
和client2
都需要更新共享对象Struct
.但是,我希望client1
首先获取锁,更新Struct
,然后将控制权传递给client2
.如果按原样运行下面的代码,则print
语句会混合在一起.
Below is the minimal code to illustrate my problem. client1
and client2
both need to update a shared object Struct
. However, I want client1
to acquire the lock first, update Struct
, and then pass control to client2
. If you run the code below as-is, the print
statements are all mixed up.
import multiprocessing as mp
from multiprocessing.managers import SyncManager
import time
class Struct:
def __init__(self):
self.a = []
def update(self, x, y):
self.a.append(x ** 2)
def get(self):
return self.a
class Server(SyncManager):
pass
global_S = Struct()
Server.register('Struct', lambda: global_S)
def server_run():
print('Server starting ...')
manager = Server(('localhost', 8080), authkey=b'none')
manager.get_server().serve_forever()
def client_run(name, x, y, wait):
server_proc = Server(('localhost', 8080), authkey=b'none')
server_proc.connect()
S = server_proc.Struct()
with server_proc.Lock():
for i in range(5):
S.update(x+i, y+i)
print(name, S.get())
time.sleep(wait)
server = mp.Process(target=server_run)
server.daemon = True
client1 = mp.Process(target=client_run, args=('c1', 3,7, 1))
client2 = mp.Process(target=client_run, args=('c2', 100,120, .6))
server.start()
time.sleep(0.3) # wait for server to spawn up
client1.start()
time.sleep(0.3)
client2.start()
client1.join()
client2.join()
示例输出:
Server starting ...
c1 [9]
c2 [9, 10000]
c2 [9, 10000, 10201]
c1 [9, 10000, 10201, 16]
c2 [9, 10000, 10201, 16, 10404]
c1 [9, 10000, 10201, 16, 10404, 25]
c2 [9, 10000, 10201, 16, 10404, 25, 10609]
c2 [9, 10000, 10201, 16, 10404, 25, 10609, 10816]
c1 [9, 10000, 10201, 16, 10404, 25, 10609, 10816, 36]
c1 [9, 10000, 10201, 16, 10404, 25, 10609, 10816, 36, 49]
推荐答案
我想出了一种解决方法.出于以下原因,请勿使用内置的SyncManager.Lock()
:
I figured out a workaround. Don't use the builtin SyncManager.Lock()
for the following reasons:
- 它每次都在创建一个新的Lock对象,而不是共享.
- 它环绕threading.Lock(),不 multiprocess.Lock().看起来不适用于多处理!
- It's creating a new Lock object every time instead of sharing.
- It wraps around threading.Lock(), NOT multiprocess.Lock(). Looks like it doesn't work with multiprocessing!
解决方案是注册您自己的锁管理器:
Solution is to register your own lock manager:
from multiprocessing.managers import BaseManager, AcquirerProxy
global_lock = mp.Lock()
def get_lock():
print('getting global_lock')
return global_lock
Server.register('Lock', get_lock, AcquirerProxy)
这篇关于如何正确使用SyncManager.Lock或Event?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!