简体   繁体   中英

How to know if a Python multiprocessing.Lock is released or not?

>>> 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

throws a ValueError exception. How can I prevent to release a lock more than once? Something like l.is_released() ?

The question is a bit unclear. You either need to use semaphores instead of locks or check if lock is locked.

Python's locks are not the same as locks on .Net, for example. Python's Lock once unlocks releases ALL other threads that acquired() on the same lock and blocked for the time being. Any thread can release and all go at the same time. So, instead of doing second relase, do

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

If you want "queue" behavior, where only one tread will get ownership of a lock once some other releases, use Semaphore, Event or some other similar class that allows nested locking and queuing behavior.

It's interesting to note that other languages/loolkits, like .Net, do lock queuing natively, where threads can pile up lock.acquire in order, block and take ownership of the lock object in the order of acquire queue, not release all at once.

(Edit: forgot to put parents as in "if l.locked: l.realse()". Corrected the code. Lock.locked is confirmed to be a present method in cPython 2.6.x, 3.x, IronPython 2.6.1)

The expectation is that the context that acquired the lock should be aware of when it should release it. In what circumstance would you attempt to release it multiple times?

Since lock.acquire() returns true if it successfully acquires the lock, you can store the state of locking in a local variable and then encapsulate lock.acquire() and the subsequent code inside a try-finally block. Then in the finally block, you can query the variable to see if the lock has been acquired or not. If it has, release.

Create a quick wrapper function to check:

from multiprocessing import Lock

l = Lock()

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM