编辑:
我已经设法";删除";其中一把锁,但它仍然很慢。有人知道其他锁在哪里吗?
class NoLock:
def __init__(self):
pass
def __enter__(self):
return self
def __exit__(self, foo=None, bar=None, baz=None):
pass
BaseManager._mutex = NoLock()
BaseProxy._mutex = NoLock()
我知道对于多处理数组,lock=False
有一个选项,但对于复杂的对象,是否也可以这样做?例如:
class Foo:
def __init__(self):
self._a = 1000
def get_a(self):
return self._a
class SharedFoo(NamespaceProxy):
_exposed_ = ('__getattribute__', '__getattr__', '__setattr__', '__init__', 'get_a')
def get_a(self):
callmethod = object.__getattribute__(self, '_callmethod')
return callmethod('get_a', ())
class FooManager(BaseManager):
pass
if __name__ == '__main__':
FooManager.register('SharedFoo', Foo, SharedFoo)
with FooManager() as manager:
for i in range(1000000):
a = foo.get_a()
processes = []
运行foo.get_a()
1000000次需要几秒钟,这太慢了(在实际程序中,我可能需要访问它数十亿次(。显然,这是由获取和释放锁引起的,所以是否可以手动管理锁,以便我只能在使用某些功能时使程序锁定?
感谢
我刚刚遇到你的问题(迟到总比不到好(。首先,我不相信您提供的代码能够运行:foo
没有定义。我也不相信函数级别上存在锁定,如下所示。我修改了方法get_a
:(1(打印出当前正在执行的线程id的开始消息,(2(睡眠2秒,(3(打印出具有当前线程id的结束消息,(4(最终返回其值。我创建了一个由2个进程组成的处理池,并向调用方法get_a
的辅助函数并行提交了两次名为foo
的SharedFoo
实例。开始和结束消息以及总运行时间清楚地表明,对get_a
的调用不是通过方法的单个线程
from multiprocessing.managers import BaseManager, NamespaceProxy
from multiprocessing.pool import Pool
from threading import get_ident
import time
class Foo:
def __init__(self):
self._a = 1000
def get_a(self):
print(f'started {get_ident()}')
time.sleep(2)
print(f'ended {get_ident()}')
return self._a
class SharedFoo(NamespaceProxy):
_exposed_ = ('__getattribute__', '__getattr__', '__setattr__', '__init__', 'get_a')
def get_a(self):
callmethod = object.__getattribute__(self, '_callmethod')
return callmethod('get_a', ())
class FooManager(BaseManager):
pass
def worker(foo):
return foo.get_a()
if __name__ == '__main__':
FooManager.register('SharedFoo', Foo, SharedFoo)
with FooManager() as manager:
foo = manager.SharedFoo()
pool = Pool(2)
t = time.time()
pool.apply_async(worker, args=(foo,))
pool.apply_async(worker, args=(foo,))
# Wait for tasks to complete:
pool.close()
pool.join()
print(time.time() - t)
打印:
started 22320
started 36068
ended 22320
ended 36068
2.1460039615631104
代理本身很慢