如何判断Python的multiprocessing.Lock是否已释放?

6 投票
4 回答
13881 浏览
提问于 2025-04-16 03:35
>>> l = Lock()
>>> l.acquire()
True
>>> l.release()
>>> l.release()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: semaphore or lock released too many times

抛出了一个ValueError异常。我该如何防止锁被释放超过一次呢?有没有类似l.is_released()这样的检查方法?

4 个回答

2

创建一个简单的包装函数来进行检查:

from multiprocessing import Lock

l = Lock()

def is_locked():
    locked = l.acquire(block=False)
    if locked == False:
        return True
    else:
        l.release()
        return False
7

大家的想法是,获取了锁的地方应该知道什么时候该释放这个锁。那在什么情况下你会尝试多次释放这个锁呢?

9

这个问题有点不太清楚。你要么需要用信号量代替锁,要么检查一下锁是否被锁住了。

Python的锁和.Net上的锁是不一样的。Python的锁一旦解锁,就会释放所有在这个锁上等待的其他线程,让它们同时继续运行。也就是说,任何线程都可以解锁,所有等待的线程都会同时被放行。所以,不用再做第二次解锁,直接用下面的代码就可以了:

if l.locked():
    l.release()

如果你想要“队列”的效果,也就是只有一个线程能在另一个线程释放锁后获得锁的控制权,那就应该使用信号量、事件或者其他类似的类,这些类可以支持嵌套锁定和排队的行为。

有趣的是,其他语言或工具,比如.Net,原生就支持锁的排队,也就是说线程可以按照顺序排队请求锁,阻塞并按照请求的顺序获得锁,而不是一次性释放所有线程。

(编辑:忘了加上括号,比如“如果 l.locked: l.release()”。已经修正了代码。Lock.locked这个方法在cPython 2.6.x、3.x和IronPython 2.6.1中都是存在的。)

撰写回答