In order to synchronize the access to any resources more efficiently, we can associate a condition with tasks, for any thread to wait until a certain condition is met or notify other threads about the condition being fulfilled so that they may unblock themselves.
Let's take a simple example to understand this. In the Producer Consumer problem, if there is one Produces producing some item and one Consumer consuming it, then until the Producer has produced the item the Consumer cannot consume it. Hence the Consumer waits until the Produced produces an item. And it's the duty of the Producer to inform the Consumer that an item is available for consumption once it is successfully produced.
And if there are multiple Consumers consuming the item produced by the Producer then the Producer must inform all the Consumers about the new item produced.
This is a perfect usecase for the condition object in multithreading in python.
wait()
, notify()
and notifyAll()
Now that we know what the condition object is used for in python multithreading, let's see the syntax for it:
condition = threading.Condition([lock])
The condition object takes in an optional lock object as argument. If we do not provide anything then it creates a default lock.
A condition object has acquire()
and release()
methods that call the corresponding methods of the associated lock. It also has a wait()
method, and notify()
and notifyAll()
methods. These three must only be called after the calling thread has acquired the lock.
Following are condition class methods:
acquire(*args)
methodThis method is used to acquire the lock. This method calls the corresponding acquire()
method on the underlying lock present in the condition object; The return value is whatever that method returns.
release()
methodthis method is used to release the lock. This method calls the corresponding release()
method on the underlying lock present in the condition object.
wait([timeout])
methodThis method is used to block the thread and make it wait until some other thread notifies it by calling the notify()
or notifyAll()
method on the same condition object or until the timeout occurs.
This must only be called when the calling thread has acquired the lock.
When called, this method releases the lock and then blocks the thread until it is awakened by a notify()
or notifyAll()
call for the same condition variable from some other thread, or until the timeout occurs.
This method returns True
if it is released because of notify()
or notifyAll()
method else if timeout occurs this method will return False
boolean value.
notify()
methodIt wakes up any thread waiting on the corresponding condition. This must only be called when the calling thread has acquired the lock. Also, calling this method will wake only one waiting thread.
notifyAll()
methodIt wakes up all the threads waiting on this condition. This method acts like notify()
method, but wakes up all the waiting threads instead of one.
In the code example below we have implemented a simple producer-consumer solution, where the producer produces an item and adds it to a list from which the consumer is consuming the items.
Few important takeaways from the code example above:
SomeItem
which has a list
which acts as the shared resource between the producer and consumer thread.This is a very simple example covering all the usecases of condition object. Try running the above program with 2 consumer threads and single producer thread.