问题描述
我正在尝试创建一个@synchronized包装器,该包装器为每个对象创建一个Lock,并使方法调用线程安全.仅当我可以在包装方法中访问该方法的method.im_self时,才能执行此操作.
I'm trying to create a @synchronized wrapper that creates one Lock per object and makes method calls thread safe. I can only do this if I can access method.im_self of the method in the wrapped method.
class B:
def f(self): pass
assert inspect.ismethod( B.f ) # OK
assert inspect.ismethod( B().f ) # OK
print B.f # <unbound method B.f>
print B().f # <bound method B.f of <__main__.B instance at 0x7fa2055e67e8>>
def synchronized(func):
# func is not bound or unbound!
print func # <function f at 0x7fa20561b9b0> !!!!
assert inspect.ismethod(func) # FAIL
# ... allocate one lock per C instance
return func
class C:
@synchronized
def f(self): pass
(1)令人困惑的是,传递给我的装饰器的func参数在传递给wrapper-generator之前更改了类型.这似乎是不礼貌和不必要的.为什么会这样?
(1) What's confusing is that the func parameter passed to my decorator changes type before it gets passed into the wrapper-generator. This seem is rude and unnecessary. Why does this happen?
(2)是否存在一些装饰器魔术,通过它们我可以对对象进行互斥(即,每个对象一个锁,而不是每个类一个锁)来进行方法调用.
(2) Is there some decorator magic by which I can make method calls to an object mutex-ed (i.e. one lock per object, not per class).
更新:@synchronized(lock)包装器有很多示例.但是,我真正想要的是@synchronized(self).我可以像这样解决它:
UPDATE: There are many examples of @synchronized(lock) wrappers. However, really what I want is @synchronized(self). I can solve it like this:
def synchronizedMethod(func):
def _synchronized(*args, **kw):
self = args[0]
lock = oneLockPerObject(self)
with lock: return func(*args, **kw)
return _synchronized
但是,因为它效率更高,所以我希望:
However, because its much more efficient, I'd prefer:
def synchronizedMethod(func):
lock = oneLockPerObject(func.im_self)
def _synchronized(*args, **kw):
with lock: return func(*args, **kw)
return _synchronized
这可能吗?
推荐答案
继续阅读:
尤其是:
- https://github.com/GrahamDumpleton/wrapt/blob/develop/blog/07-the-missing-synchronized-decorator.md
- https://github.com/GrahamDumpleton/wrapt/blob/develop/blog/08-the-synchronized-decorator-as-context-manager.md
wrapt
模块然后包含此处描述的 @synchronized
装饰器.
The wrapt
module then contains the @synchronized
decorator described there.
完整的实现足够灵活,可以执行以下操作:
The full implementation is flexible enough to do:
@synchronized # lock bound to function1
def function1():
pass
@synchronized # lock bound to function2
def function2():
pass
@synchronized # lock bound to Class
class Class(object):
@synchronized # lock bound to instance of Class
def function_im(self):
pass
@synchronized # lock bound to Class
@classmethod
def function_cm(cls):
pass
@synchronized # lock bound to function_sm
@staticmethod
def function_sm():
pass
还有上下文管理器之类的用法:
Along with context manager like usage as well:
class Object(object):
@synchronized
def function_im_1(self):
pass
def function_im_2(self):
with synchronized(self):
pass
其他信息和示例也可以在以下位置找到:
Further information and examples can also be found in:
您还可以通过以下方式进行会议演讲:
There is also a conference talk you can watch on how this is implemented at:
这篇关于可以创建一个知道方法对象的@synchronized装饰器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!