0

I'm using threading.RLock for a multithreaded application. I'd like to have threads try to acquire a lock, and if unsuccessful, retry some number of times provided the time spent retrying is below some timeout threshold.

Here's what I have

>>> import threading
>>> lock = threading.RLock()
>>> def worker():
        with lock.acquire(timeout=5):
            print('acquired')
>>> lock.acquire()
>>> t2 = threading.Thread(target=worker)
>>> t2.start()

This seems to work, and I get an exception after five seconds of waiting:

>>> Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)
  File "<pyshell#7>", line 2, in test
AttributeError: __exit__

KeyboardInterrupt
>>> 
KeyboardInterrupt

The AttributeError seems strange - shouldn't we see some kind of a timeout error?

My questions here are:

  1. Am I doing this correctly in Python 3.4? I've been looking at a similar question asked on SO that seems targeted to Python 2.7. Moreover, I'm somewhat confused why I'd need to use a condition variable if lock.acquire accepts a timeout argument.
  2. Is there a better pattern for retrying lock.acquire with a timeout/delay in between retries?

1 Answers1

0

Locks are context managers, but acquire doesn't return a context manager. It also doesn't throw an exception if it times out.

Lock.acquire and RLock.acquire return True if they acquire the lock and False if they don't. To test whether you acquired the lock, simply check the return value. Don't use with or try-except.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Ah! That makes sense why I'm getting the attribute error - it's not a context manager - Thanks! I'm wondering if you might be able to also clear up the confusion regarding the linked question. Should I be using a condition variable, here? – user138440 Oct 09 '17 at 00:52
  • @user138440: You don't need a condition variable. The linked question needs to emulate `timeout` because `Lock.acquire` and `RLock.acquire` don't support `timeout` on Python 2. – user2357112 Oct 09 '17 at 00:55