We can use Re entrant locks to enforce thread safety.
Critical sections of your code must be accessed in serial.
When multithreading, you need to lock critical sections of your code.
And so in this lesson, you will use a re-engagement lock to lock a critical part of your code.
First things first opened up the folder for this lesson by following this path in your course resources.
First, let's talk about what a race condition is, a race condition is an incorrect computation that
results from too many threads trying to update or access the same resource.
And so critical code is code that is vulnerable to race conditions.
That being said, your app is going to be vulnerable to race conditions if many threads are able to
access or update critical code at the same time.
So open up that Java here we have a task method that increments a counter variable 10000 times in a
single threaded context.
This code is going to work just fine.
And so in Maine, if I happen to call this really long task twice the task task.
You would expect that after printing the counter, we should get 20000.
Run our code.
And you would be correct again in a single threaded context right now, we're just using one thread.
This is pretty basic stuff.
Everything is just running on the main thread.
The first loop will call it task.
One keeps incrementing until 10000.
The second loop will call it task two increments until 20000.
This is pretty basic stuff.
The key takeaway is that our counter is being updated in serial fashion, but using our imagination,
we're going to say, OK, there are some really long operations in this method.
We need to use multi-threading so that we do not block the main threat.
For now, let's forget about thread pools and all that and just create two thread objects.
So we'll see thread.
The red one is equal to new thread.
That executes a runnable task.
Analysts say Thread Threat two is equal to a new thread once again takes in a renewable task.
But.
All right, then we can say through at one point start.
Threat to Dodge Dart.
And after we make sure that both threads have finished executing their tasks, so by saying thread one
day join and thread to join, only then are we going to print the counter variable.
This needs to be wrapped in a try catch block.
We'll just catch whatever exception comes out of this, it doesn't matter what it is right now.
And we'll print the message.
I'll give you some time to write that out.
You know, if I were to run this code, are you going to get 20000, if only?
Ten thousand seven hundred and sixty four.
You probably got something completely different, depending on how your task scheduler was scheduling
your tasks.
But nonetheless, our code was vulnerable to a race condition.
Remember that a race condition is an incorrect computation that results from many threads trying to
update the same resource.
And your app is vulnerable to race conditions if many threads access or update critical code at the
same time.
How do you identify a critical code?
It's right here.
This line is critical because if two threads executed at the exact same time, you're going to get a
race condition the line counter plus plus.
Remember, if we go back to section two stuff counter plus plus as the same thing as saying counter
+1.
All right.
MS. commented out.
Let's imagine a fully concurrent scenario.
Forget the main thread.
Let's assume the red one and threat to our both being processed by the same core.
The threads run concurrently because we're making progress on two threads at the same time.
Careful.
We're not running two threads at the same time.
We're making progress on two threads at a time.
So first, it'll run this thread.
Let's say it updates the calendar twice and then another thread updates the counter four times.
Now we're at six.
If the execution is fully concurrent, where one core is constantly alternating between two threads,
then we shouldn't have any problems.
But you can never guarantee that because the task scheduler is really random.
What if Threat two is being processed by another court?
In this case, the two threads will run in parallel.
And let's see, the counter is at 2000, imagine both threads.
Read this Part of the code at the exact same time counter is equal to counter.
So they're both going to think, OK, the counter is 2000, and by adding one, it's two thousand and
one.
So the increment operation happened twice, but counter only went up by one.
And that's because two threads happened to access and update the exact same resource at the same time.
This is a race condition, and it's what makes multi-threading extremely unsafe.
And the answer to thread safety is resentment Lux.
Resentment locks can lock critical sections of your code.
They ensure that critical code is accessed in serial fashion, meaning one at a time.
And you can create a lock by creating a new object of the re-enter into the class, which we're going
to do right now, re-enter and lock.
Luck.
Is equal to a new object of the resentment law class.
And we need to look this critical part of our code.
So we're going to pass this lock into our task method.
It's going to receive a RE entrant lock.
We're going to lock this part of our code locked up lock.
We can go ahead and remove these comments.
We don't really need them anymore.
And once one of the threads has finished running this code, then we can unlock it so that the other
thread can then access it.
Ultimately, this is going to make sure that Counter Plus Plus only gets access to one thread at a time,
thus enforcing thread safety.
So if I were in the code.
Everything works.
How exactly is locked up, lock and unlock and forcing thread safety?
Let's take the example where each thread is running on its own core, which means they're going to be
running in parallel once again.
Imagine both threads get to this part of the code.
It's going to lock for one of the threads.
In this case, it's telling thread to hear you at your turn thread.
One does its thing.
And after a thread, one is finished, the code basically unlocks for Thread two, which was patiently
waiting its turn.
Ghosn updates the counter and just like that by locking a critical section of our code.
There is no possibility of there being a race condition.
So to recap, use RE entrant logs to enforce thread safety, your app is vulnerable to race conditions
if many threads are accessing and updating critical code at the same time.
Use locks to ensure that critical sections of your code are running in serial.