可以创建一个知道方法对象的

可以创建一个知道方法对象的

本文介绍了可以创建一个知道方法对象的@synchronized装饰器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个@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

这可能吗?

推荐答案

继续阅读:

尤其是:

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装饰器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 18:28