В общем, вы должны устанавливать блокировки только вокруг границ критических секций или использования общих ресурсов.Вы должны рассмотреть, что именно вы пытаетесь защитить от одновременного доступа, и защитить его.Если, например, у класса A есть Очередь, в которую помещаются и считываются элементы, то вам следует защищать доступ к этому конкретному ресурсу.Поскольку ООП диктует, что к этому виду ресурсов должны обращаться только методы класса, его должен защищать только класс 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'or класса, то вам нужна либо глобальная блокировка для модуля, созданная и инициализированная вне области действия класса, либо добавление блокировки к объекту 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