So, guys, now in this section of the course, we will start with the thread synchronization.
So thread synchronization is the hardest and the most important aspect of multi threading thread Synchronization
is required in multi threaded programs where multi threads competes to perform conflicting operations
on a shared resource.
Now a conflicting operations is a read write operation or write write operation.
Right?
So consider you have a process P and this process P has two threads the thread T1 and the thread T2
right.
And both the threads, T1 and T2 are running concurrently and trying to perform some operation on a
shared resource represented by this letter D Right.
Now, this letter D is a shared resource, which could be a heap data structure, which could be a global
variable, which could be some file descriptor, let's say open file, or it can represent socket,
or it could be some data which has been received from external sources via multiple inlets.
So if thread T1, for example, let's say the thread T1 is performing read operation on a shared resource
T and the thread T2 is trying to perform a write operation on a shared resource D.
Then these two operations will set to be a conflicting operations, right?
Similarly write write operation are also conflicting operations.
But if the two threads or more than two threads try to perform only read operations on a shared resource,
then those read operations are not conflicting operations.
So only read operation is not a conflicting operation, but read, write or write.
Write.
Operations are conflicting operations.
So let us first try to understand the problems we would have if we don't have a thread synchronization,
right?
So let us try to discuss some sort of problems which will have.
So consider a multi threaded process P which have two threads the thread T1 and thread T to also consider
that a process P maintains a linked list of integers.
So let us say there is a process P and one of the internal data structure of the process P is a linked
list of some integers.
Right?
So now the two threads t one and T two can be scheduled on the CPUs of the machine in any order.
You cannot assume any determinism or pattern of scheduling of threads on the CPU.
Your operating system schedule the threads on the available CPUs of your machine as per their scheduling
algorithm while writing a program.
You just cannot assume or make any assumption that the threads of your program will going to be scheduled
in so and so order.
You just cannot assume anything.
So now let us consider that the thread t one is executing this function on a link list and the thread
t two is executing this particular function on a link list.
That is the same link list.
Now the first thread is trying to look up a node from the link list based on some integer input value.
Right.
So the function is get node from the list and the thread t one simply invokes some internal functions.
Let us say search node which walks over this link list and find the matching node and return that node
right.
Similarly, thread T two is performing a delete operation on the same link list.
That is, it searches the node in the link list and once the node is found it removes the node from
the link list and free the node memory.
Right.
So you can assume that the thread t1 and thread t two are executing concurrently on different CPUs of
the machine.
Right.
Now let us try to see what could go wrong if the thread t one and t two are allowed to execute concurrently
on different CPUs of the machine without having deployed any thread synchronization.
So let us suppose that the thread t one has successfully executed the instruction I1 and i2, but it
has not yet executed the instruction.
I4 Right.
So it means that the thread T1 has executed an instruction i1 i2 or let us say i3, but instruction
I4 is still pending and then the context switching happens and the thread t2 is loaded on the CPU.
Right?
So now when the threat T2 is loaded on the CPU, let us assume that threat T2 has executed all the instruction
that is instruction i6 i7 i8 I9 and I10.
Right.
Let us also assume that the threat T1 invoked its function on the input value, say five right and the
threat T2 was also invoked its function delete node from the list with the input value say five.
It simply means that while threat T1 is trying to look up a node from the link list whose value is five,
whereas threat T2 is trying to delete a same node from the link list whose value is five.
Right.
Now you can see that the thread two when executed it deleted the node from the link list and eventually
freed the node memory.
Right.
Now let us suppose that once the thread T2 has completed its execution, the thread T1 is loaded again
on the CPU.
Now the thread T1 will resume its execution from the same point where it had left.
So now the thread T1 will try to execute the instruction I4 and it will try to return a pointer to the
node.
But now remember the thread T2 has already freed that particular memory.
It means that thread T1 is now returning an address of the memory which is already freed.
Right.
So the caller function which invoked this API was going to crash because it will go into deal with the
address which is already freed.
Right.
So you can see that the thread to perform the right operation on the data structure link list, whereas
the thread T1 is trying to perform read operation on the same data structure that is same link list.
So this is the example where read and write operations are conflicting with each other.
Any program which deploys the threat.
T1 and T2, which performs the conflicting read and write operations could show any undefined behavior
and can crash any time.
So concurrent access of the shared data structures between multiple threads opens a window during which
data is inconsistent.
And the root cause is concurrency because you have allowed the two threads T1 and thread T2 to execute
in a concurrent manner on different CPUs without thread synchronization techniques.
Your program has been exposed to concurrency problems and this is one of many examples of data inconsistency
due to allowing the execution of multiple threads without thread synchronization techniques.
So the reason in code where shared data is accessed by multiple threads are called critical sections.
So in this slide, the yellow color region which you are seeing on the slide are the critical section.
This is the critical section and this is also the critical section.
Why?
It is a critical section because your threads are trying to access the data structure which is shared
between two threads here.
That data structure is this link list, right?
So our goal is that that we should still allow the threads to execute in a concurrent manner, while
at the same time we need to ensure that multiple threads access the shared resources of the process
in a consistent manner.
This is one example where Thread P1 returns the bogus node which was already freed by the thread t2
Right.