在python中暂时释放锁定

时间:2010-09-01 13:25:56

标签: python multithreading locking

我有许多不应该同时运行的不同方法,因此我使用单个锁来同步它们。看起来像这样:

selected_method = choose_method()
with lock:
    selected_method()

在其中一些方法中,我有时会调用辅助函数来执行一些缓慢的网络IO。 (我们称之为network_method())。我希望在此函数运行时释放锁定,以允许其他线程继续处理。

实现此目的的一种方法是在调用网络方法之前和之后调用lock.release()和lock.acquire()。但是,我更倾向于保持方法对锁定一无所知,因为它们中有很多并且它们一直在变化。

我更希望重写network_method(),以便检查是否保持锁定,如果是,则在开始之前将其释放并在结束时再次获取。

请注意network_method()有时会从其他地方调用,所以如果它不在持有它的线程上,它就不应该释放锁。

我尝试在Lock对象上使用locked()方法,但该方法只告诉我是否保持锁定,而不是当前线程保持锁定。

顺便说一下,lock是一个全局对象,我很好。

2 个答案:

答案 0 :(得分:1)

  

我更喜欢重写network_method(),以便检查是否保持锁定,如果是,则在开始之前将其释放并在结束时再次获取。

     

请注意,network_method()有时会从其他地方调用,所以如果它不在持有它的线程上,它就不应该释放锁。

这听起来完全是错误的事情:(

首先,有一个功能,有时会有一些其他神奇的副作用,这取决于你从哪里调用它是很糟糕的。这就是调试的噩梦。

其次,锁应具有明确的获取和释放语义。如果我查看代码“lock(); do_something(); unlock();”然后我希望它在do_something()的持续时间内被锁定。事实上,它也告诉我do_something()需要一个锁。如果我发现有人写了一个特定的do_something()实际上解锁了我刚刚看到锁定的锁,我将(a)解雇他们或(b)用武器追捕他们,这取决于我是否在相对于他们的资历与否。

  

顺便说一下,lock是一个全局对象,我很好。

顺便说一句,这也是全局变坏的原因。如果我修改了一个值,调用一个函数,然后再次修改一个值,我不希望中间的那个函数能够以不可预测的方式返回并修改这个值。

我对你的建议是这样的:你的锁是在错误的地方,或做错了什么,或两者兼而有之。你说这些方法不应该同时运行,但你实际上希望它们中的一些同时运行。其中一个“慢”的事实不可能使锁定被移除 - 在这种类型的操作中你需要互斥以使其正确,或者你不需要。如果较慢的操作确实是安全的,而其他操作确实不安全,那么它可能不需要锁定 - 但这意味着锁定应该进入每个更快的操作,而不是在它们之外。但所有这一切都取决于锁的确切含义。

答案 1 :(得分:0)

为什么不这样做?

with lock:
    before_network()
do_network_stuff()
with lock:
    after_network()