In multithreading when multiple threads are working simultaneously on a shared resource like a file(reading and writing data into a file), then to avoid concurrent modification error(multiple threads accessing same resource leading to inconsistent data) some sort of locking mechanism is used where in when one thread is accessing a resource it takes a lock on that resource and until it releases that lock no other thread can access the same resource.
threading module of Python, for efficient multithreading a primitive lock is used. This lock helps us in the synchronization of two or more threads. Lock class perhaps provides the simplest synchronization primitive in Python.
Primitive lock can have two States: locked or unlocked and is initially created in unlocked state when we initialize the Lock object. It has two basic methods,
Following is the basic syntax for creating a Lock object:
import threading threading.Lock()
Lock objects use two methods, they are:
This method is used to acquire the lock. When it is invoked without arguments, it blocks until the lock is unlocked.
This method can take 2 optional arguments, they are:
Falsewill not block the thread if the lock is acquired by some other thread already and will return
Falseas result. If you provide the value for this blocking flag as
Truethen the calling thread will be blocked if some other thread is holding the lock and once the lock is released then your thread will acquire the lock and return
It is used to release an acquired lock. If the lock is locked, this method will reset it to unlocked, and return. Also this method can be called from any thread.
When this method is called, one out of the already waiting threads to acquire the lock is allowed to hold the lock.
Also, it throws a
RuntimeError if it is invoked on an unlocked lock.
Below we have a simple python program in which we have a class
SharedCounter which will act as the shared resource between our threads.
We have a
task method from which we will call the
increment() method. As more than one thread will be accessing the same counter and incrementing its value, there are chances of concurrent modification, which could lead to inconsistent value for the
Takeaways from the code above:
acquire()method and then access a resource, what if during accessing the resource some error occurs? In that case, no other thread will be able to access that resource, hence we must access the resource inside the
tryblock. And inside the
finallyblock we can call the
release()method to relase the lock.