Is there a way to implement a lock in Python for multithreading purposes whose acquire
method can have an arbitrary timeout? The only working solutions I found so far use polling, which
Is there a better way to implement this?
Using Lock to prevent the race condition To prevent race conditions, you can use the Lock class from the threading module. A lock has two states: locked and unlocked. By default, the lock has the unlocked status until you acquire it.
A lock can be locked using the acquire() method. Once a thread has acquired the lock, all subsequent attempts to acquire the lock are blocked until it is released. The lock can be released using the release() method. Calling the release() method on a lock, in an unlocked state, results in an error.
Applying timeout function using thread in PythonThe first thread is to execute the function. 2. The second thread is to measure the time taken by the function. The only second thread should whether the time is over or not.
You can lock a variable to make it thread-safe using a threading. Lock. In this tutorial you will discover how to lock a variable in Python.
to elaborate on Steven's comment suggestion:
import threading import time lock = threading.Lock() cond = threading.Condition(threading.Lock()) def waitLock(timeout): with cond: current_time = start_time = time.time() while current_time < start_time + timeout: if lock.acquire(False): return True else: cond.wait(timeout - current_time + start_time) current_time = time.time() return False
Things to notice:
threading.Lock()
objects, one is internal to the threading.Condition()
. cond
, it's lock is acquired; the wait()
operation unlocks it, though, so any number of threads can watch it.threading.Condition
can become notified for reasons other than timeouts, so you still need to track the time if you really want it to expire.waitLock
function should follow a lock.release()
with a cond.notify()
so that other threads waiting on it are notified that they should retry aquiring the lock. This is not shown in the example.My version using thread safe queues http://docs.python.org/2/library/queue.html and their put/get methods that supports timeout.
Until now is working fine, but if someone can do a peer review on it I'll be grateful.
""" Thread-safe lock mechanism with timeout support module. """ from threading import ThreadError, current_thread from Queue import Queue, Full, Empty class TimeoutLock(object): """ Thread-safe lock mechanism with timeout support. """ def __init__(self, mutex=True): """ Constructor. Mutex parameter specifies if the lock should behave like a Mutex, and thus use the concept of thread ownership. """ self._queue = Queue(maxsize=1) self._owner = None self._mutex = mutex def acquire(self, timeout=0): """ Acquire the lock. Returns True if the lock was succesfully acquired, False otherwise. Timeout: - < 0 : Wait forever. - 0 : No wait. - > 0 : Wait x seconds. """ th = current_thread() try: self._queue.put( th, block=(timeout != 0), timeout=(None if timeout < 0 else timeout) ) except Full: return False self._owner = th return True def release(self): """ Release the lock. If the lock is configured as a Mutex, only the owner thread can release the lock. If another thread attempts to release the lock a ThreadException is raised. """ th = current_thread() if self._mutex and th != self._owner: raise ThreadError('This lock isn\'t owned by this thread.') self._owner = None try: self._queue.get(False) return True except Empty: raise ThreadError('This lock was released already.')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With