我正在尝试使用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"
那有道理吗?如果我还没有锁,我基本上只想做这个。
除了能够实现这一点,它是一个糟糕的设计?我应该自己获得/释放吗?
答案 0 :(得分:37)
只需使用可重入的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
以外的其他人调用?
答案 1 :(得分:5)
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解决方案看起来像一个胜利者。但是,此解决方案可能在不同的上下文中有用。
答案 2 :(得分:1)
为什么不:
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的更具体的批评是,创建可重入锁的行远离以可重入方式获取锁的代码。如果有人说重入锁与另一个不可重入的锁或者更改创建锁的行,那么这有点脆弱。
答案 3 :(得分:0)
使用with语句优于acquire()
和release()
函数。这样,如果发生错误,锁将被释放。
答案 4 :(得分:0)
with语句是实现锁定的好方法,因为锁定是一种完美的资源获取模式。虽然,你当前的例子不起作用,但你需要在somethingElse()中围绕with语句使用if语句。