我怎么能锁定整个班级

时间:2011-08-27 13:34:58

标签: python oop

我有以下伪代码:

class A:
    mutex lockForB

class B:
    def __init__(self, A): //the type of A is class A
        lock(A.lockForB)
        # ...
        unlock(A.lockForB)

    # other function have the same locking

我从oop的角度理解使用这样的设计是非常糟糕的,但如果我在B类中创建锁,我将无法锁定B类的创建者。有没有更好的设计呢?提前谢谢。

2 个答案:

答案 0 :(得分:3)

我不知道你想要完成什么。类级别锁定不太可能是您想要的,但您的伪代码与实际代码的距离不是很远,所以我只填写空白。老实说,如果你不知道你试图同步访问它,那将是一个帮助你的挑战。

class A:
    lockForB = threading.RLock()

class B:
    def __init__(self): 
        with A.lockForB:
            # do init stuff

    def othermethod(self):
        with A.lockForB:
            # do other stuff

这样代码就可以了。 lockForB只是A上的一个类级别属性,因此它在A的所有实例之间共享。但是,在我看到人们使用这样的类级别锁的情况下,通常是为了防止拥有该锁的类被放入一个不一致的状态,你有两个看似无关的类共享一个锁。

如果没有上下文来帮助理解你试图同步访问它的内容,很难告诉你为什么不能这样写:

class C:
    lock = threading.RLock()
    def __init__(self):
        with self.lock:
            # do stuff
    def othermethod(self):
        with self.lock:
            # do other stuff

答案 1 :(得分:1)

通常,您应该仅在关键部分的边界或共享资源的使用周围放置锁。你应该考虑一下你试图保护它免受同时访问并保护它。例如,如果A类具有放置和读取项目的队列,那么您应该保护对该特定资源的访问权限。由于OOP规定只能通过类方法访问此类资源,因此只有A类应该保护它:

class A(object):
    def __init__(self, *args, **kws):
        # do the initialization
        self._my_queue = Queue()
        self._lock = Lock()

    def do_something(self):
        # do initial calculations
        self._lock.acquire()
        item = self._my_queue.get()
        self._lock.release()
        # do other things

因此,B类应该调用A类方法,它将是线程安全的。如果B类有自己的关键部分,那么使用多个锁是非常好的:

class B(object):
    def __init__(self, *args, **kws):
        # do the initialization
        self._lock = Lock()
        self.a = A()

    def do_something_with_a(self):
        # initial calculations
        self._lock.acquire()
        # Critical section
        result = self.a.do_something()
        # do something with result
        self._lock.release()
        # continue the code

这样每个类都可以保护自己的关键部分和共享资源,而且不需要破坏类接口。

如果你需要保护类的C'tor,那么你需要一个模块的全局锁,在类的范围之外创建和初始化,或者将锁添加到Class对象(就像静态成员一样)在C ++和Java中而不是实例本身:

class B(object):
    def __init__(self, *args, **kws):
        if not hasattr(self.__class__, "_lock"):
            self.__class__._lock = Lock()
        # works with Python 2.6+ for earlier version use try-finally
        with self.__class__._lock: 
            # Your initialization

这将保护你的C'tor