Python 条件性 "With" 锁设计

36 投票
5 回答
72208 浏览
提问于 2025-04-16 12:57

我正在尝试使用“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"

这样理解吗?我基本上只想在我还没有锁的时候才使用“with”。

除了能做到这一点,这样的设计会不好吗?我是不是应该自己去获取和释放锁?

5 个回答

2

使用with语句比单纯使用acquire()release()函数要好。这是因为如果出现错误,锁会自动释放。

8

在Python中,or是一个“短路”操作,这意味着你可以让锁的使用变得有条件:

def somethingElse(self, hasLock = False):
    #I want this to be conditional...
    with hasLock or self.my_lock:
          print 'i hate hello worlds'

不过,这事并没有那么简单,因为布尔值(也就是True或False)不能直接作为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的解决方案看起来更好。不过,这种方法在其他情况下可能会有用。

64

你可以使用一个叫做 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 调用的?

撰写回答