RLock Object - Re-entrant Lock in Python
If you try to run the code provided below, the lock object will acquire the lock the first time acquire()
method is called but not the second time.
Why is that? Well because the normal lock object once acquired cannot be re-acquired even if the same threads attempts to do so.
But why would someone try to call the acquire()
method twice? Let's take a simple example to demonstrate this simple locking issue:
lock = threading.Lock()
def get_first_line():
lock.acquire()
try:
# read some file and get the first line
finally:
lock.release()
return data
def get_second_line():
lock.acquire()
try:
# read the same file and get the second line
finally:
lock.release()
return data
In the code above we have two different functions reading different parts of data from a shared resource. We have used locking mechanism to prevent any other thread from modifying the data of the file while our thread is reading it.
Now consider that you want to call both the functions one by one, you will do this:
first = get_first_line()
second = get_second_line()
return first, second
But this call is still not thread safe because while you are reading the data from the shared resource, there can be any other thread which can modify the content of the shared resource in between the two function calls.
To avoid that, we can get a lock and then call these two functions:
lock.acquire()
try:
first = get_first_line()
second = get_second_line()
finally:
lock.release()
return first, second
But, this code will not work, because, we will be calling acquire()
on the lock object inside the same thread trying to acquire the lock again inside the functions which we have already acquired before calling the functions.
Hence in such a situation, the primitive Lock object cannot be used. For such a case we have the RLock
class.
RLock Object: Python Multithreading
An RLock stands for a re-entrant lock. A re-entrant lock can be acquired multiple times by the same thread.
RLock object also have two methods which they can call, they are:
- the
acquire()
method
- the
release()
method
Here is a simple example to demonstrate the working of RLock
object:
And the code in the simple locking issue example, will also work without any issue if we use the RLock
object:
lock = threading.RLock()
lock.acquire()
try:
first = get_first_line()
second = get_second_line()
finally:
lock.release()
return first, second
The above code will work fine.