So guys, now let us try to understand the condition variables.
So condition variables allow us to have finer control over taking the decision on when and which competing
thread to block or resume.
Now, competing threads are the set of threads which are competing to get an access to a shared resource
of a program.
Right.
We call those set of threads as competing threads.
So condition variables give a finer control over taking the decision on when and which competing thread
to block and resume.
Right.
So don't worry, maybe this definition do not make much sense.
As of now, we will go into discuss plenty of examples on condition variables.
Let us try to discuss condition variables with the help of an example.
So, for example, let us suppose that you have a thread T1 in your program and the thread T1 during
the course of its execution finds a queue empty.
Now this queue is any queue or any data structure which is being maintained by a program, and this
queue has some data elements in it.
Right.
What those data elements are.
It is not important for this discussion here.
The thread T1 is a consumer thread which wants to just consume one element from this queue.
Here.
Consuming the element means removing the element from this queue and then process that element.
Right?
So here thread T1 is a consumer thread which is trying to consume this particular queue.
Right?
So the thread t1 finds the queue empty.
It means that the thread t1 really do not have anything to consume from the queue.
Right.
So it means that our thread T1 wants to wait until some other thread of the process put an element in
the queue.
Right.
So the thing to be noted here is that that the thread T1 chooses to block itself based on the condition
that the queue is empty.
Right?
It would not have blocked itself if there was an element in the queue, but since the queue is empty,
therefore thread T1 has nothing to consume and therefore thread T1 decides to wait itself or block itself
until some other thread of the process places an element in the queue.
Right.
Once the element is placed in the queue, our thread which is in the blocked state now will be resumed
and it will consume the element from the queue.
Right.
So this is one example.
So condition variable allows threat to get itself blocked or wake up when certain condition is met.
Right.
And this is what we discussed in this example.
Right?
So you can see that condition variables allows the threat to get blocked or wake up when certain conditions
are met.
Right.
So now you must be thinking that, okay, we have a condition variable which serves this purpose, then
why we had mutex in the first place.
How condition variables are different from indexes.
Can you write a paragraph or a short note on this at this point of time?
Please think about it.
So mutex is only says that go ahead.
If you have an access over the shared resource and if that particular shared resource is already blocked
or locked by some other thread, then the current thread has no choice but to wait.
Right.
So mutex is like saying either you have an access or you don't have an access.
Right.
Consider an example on the right hand side where the red box represents the critical section which is
being executed by the thread T1 right now.
Since the thread T1 is already executing in this critical section, it simply means that the thread
T1 has successfully gained a lock on the mutex m and this mutex M is associated with this critical section,
right?
So thread T1 has successfully gained a lock on this mirax and therefore the rest of the threads of the
process that is thread t2, t3, T4 and T5 are simply blocked and prevented from entering the critical
section.
Right.
Now here, one thing to be noted here is that that the condition on which the thread T2, T3, T4 and
T5 have decided to wait and block themselves is that that the mutex which they are trying to lock is
already locked by the thread.
T1 Right.
There is no other condition.
There is only one condition that the mutex which these threads are trying to lock is already locked
by some other thread.
So this is what here mutex says that if the mutex is already locked then the thread which is trying
to lock the mutex again would get blocked.
So in this diagram, when the threat t one leaves the critical section, the lock is granted to the
blocked threat.
That is one of the threads among threat T2, T3, T4 and T5 and that thread would be chosen by the kernel
scheduling policy.
Here, programmer has little control as to which thread would go next into the critical section.
So why do we need condition variables?
Let us see that, in which scenarios the mutexes will fail and you really cannot implement the logic
using Mutexes alone.
So using mutexes we can't implement the below logic.
That is, if the thread finds some queue empty, then the thread chooses to wait until the queue has
some element in it.
Right now in this example, if the thread finds the queue empty, the thread chooses to block itself.
Right.
So here we have a customized condition and that customized condition is that that the queue is empty.
Right?
If the queue is empty, the thread decides to block itself.
So using mutexes we cannot implement this logic that is condition based blocking.
Right.
And we need condition variables for this.
So note the term here condition based locking and that is why the condition variable is so named the
condition variable.
Right?
That is block on certain conditions here you don't see any such customized or user defined condition.
The only condition is that that the that the mutex which the thread trying to lock is already locked.
There is no scope of defining user defined condition and taking a decision whether to block the threads
or not.
So now do not think that condition variable is a superset of mutex or condition.
Variable replaces the murex no condition variable plus Murex combo is what it all takes to implement
any advanced thread synchronization scheme, so you can assume that condition variable and mutexes are
like Romeo and Juliet.
Both are required to implement advanced thread synchronization techniques such as monitors or standard
problems such as producer, consumer problem dining, philosophers problem or implementing complex libraries
which could schedule the threads of the process.
Implementing other thread synchronization data structures such as semaphores, wait, queues, barriers,
etcetera.
Right.
You need to use condition variables and mutex both.
In fact, you cannot use condition variable without mutex.
So we will going to discuss how to use condition variables and mutexes together as we progress towards
implementing advanced thread synchronization programs.