我正在尝试使用with语句进行一些共享锁定
def someMethod(self, hasLock = False):
with self.my_lock:
self.somethingElse(hasLock=True)
def somethingElse(self, hasLock = False):
#I want this to be conditional...
with self.my_lock:
print 'i hate hello worlds"
有道理?如果我还没有锁,我基本上只想做。
除了能够实现这一点,它是一个糟糕的设计?我应该自己获得/释放吗?
只需使用可重入的threading.RLock
,这意味着它可以被同一个线程多次获取。
http://docs.python.org/library/threading.html#rlock-objects
为清楚起见,RLock
用于with
语句,就像在示例代码中一样:
lock = threading.RLock()
def func1():
with lock:
func2()
def func2():
with lock: # this does not block even though the lock is acquired already
print 'hello world'
至于这是否是糟糕的设计,我们需要更多的背景。为什么两个函数都需要获取锁? func2
什么时候被func1
以外的东西叫?
Python or
是short circuiting所以你可以使锁定条件:
def somethingElse(self, hasLock = False):
#I want this to be conditional...
with hasLock or self.my_lock:
print 'i hate hello worlds'
不幸的是,它并不那么容易,因为布尔值不是来自with
语句的有效返回。您需要使用__enter__
和__exit__
创建一个类来包装布尔值True
。
这是我没有测试过的一种可能的实现方式。
from contextlib import contextmanager
@contextmanager
def withTrue():
yield True
def withbool(condition):
if condition:
return withTrue()
return False
def somethingElse(self, hasLock = False):
with withbool(hasLock) or self.my_lock():
print 'i hate hello worlds'
对于这么简单的东西来说,这是很多样板,因此RLock解决方案看起来像赢家。但是,此解决方案可能在不同的上下文中有用。
为什么不:
def someMethod(self):
with self.my_lock:
self.somethingNoLock()
def somethingElse(self):
with self.my_lock:
self.somethingNoLock()
def somethingNoLock(self):
print 'i hate hello worlds"
请注意,虽然someMethod
和somethingElse
在我的解决方案中是相同的,但总的来说它们会有所不同。您可以在somethingNoLock
周围放置另一个包装器,以便锁定获取和释放不会重复多次。
这简单明了。仅仅因为可重入锁定锤是可用的,我不建议在有更直接,更不易碎的方法来钉它时使用它。
对rlock的更具体的批评是,创建可重入锁的行远离以可重入方式获取锁的代码。如果有人说重入锁与另一个不可重入的锁或以其他方式更改创建锁的行,则这有点脆弱。
使用with语句比acquire()
和release()
函数更好。这样,如果发生错误,将释放锁。
with语句是实现锁定的好方法,因为锁定是一种完美的资源获取模式。虽然,您当前的示例不起作用,但您需要在somethingElse()中的with语句周围使用if语句。