so let's take a look at another way that a deadlock can occur
let's suppose we've got two classes that contain synchronized methods and each
class calls a method in the other class now as it turns out this is a difficult
situation to make happen on purpose so we won't be actually adding code
to our application and that's why I'm showing you this in slides so we're going to
discuss the following code that you can see on the screen here now
recall that when the threads running an object synchronized method no other
thread can run a synchronized method using the same object until the first
thread exits the methods that it's running
so let's assume that we're going to use the above two classes on the previous
screen and I'll go back to that screen shortly going to use it in the following
way
so you can see that are we creating a new data object
we're creating a new display object and we're now passing the display class to
the data task via the set display method
secondly were also passing the data class to the set data method which is
part of the display class and just going back looking into that code again you
can see they are really quite simple classes so there's nothing too terribly
complicated about it
pretty straightforward
now if one thread thread one calls data .update data while another thread
thread 2 calls display.update display their are scenarios that could
potentially play out depending on timing number one thread one enter data.
updatedata and writes to the console then suspends thread 2 enters display.
updatedisplay and writes to the console and suspends thread 1 runs and tries to
call display.datachanged but thread 2 is still running display.
updatedisplay so it's holding the lock on the display object and therefore
thread 1 blocks and number 4 thread 2 wakes up and tries to run data.get
data but thread 1 is still running data.update data so thread 2 blocks
so at that
point we've got a deadlock so the underlying cause of the deadlock is
actually the same as the first example we saw in the code in the previous
lecture the two threads are trying to get the same two locks in a different
order
thread 1 wants to get the data lock and then once the display lock but
thread 2 gets the display lock and then once the data lock
now we would avoid this problem in the same way we did in the first example in
the previous video
we have to rewrite the
code so that the two threads try to obtain the locks in the same order which
in this case would mean not calling each other in this circular fashion
we could also see if it's possible to pass information to other objects using
parameters rather than having them call methods to get the information and I
feel compelled to actually say that in a real world application we wouldn't be
mixing UI and model code like this is just really serving and it's serving to
show you an example of deadlocks ok so moving on
ok so here's another way that we're going to put some code together to
get a deadlock
that's actually quite difficult to spot we're going to create a new console
project so we're going to close this one down
actually I'm just come in here and create a new project new project we're going to
select java as we always do
and create a project from template it's going to be a command line app and
will call this one say hello and will create that
and just overwrite that it will just close this other project down because we
no longer need that for now
alright so we're going to start by adding a polite person class to the main
java file I'm going to come down here and add it as inner class
....and we're going to have a private....
and we need a constructor it will pass the parameters to the constructor and
save it into our field also want a getter
getter will be on the string as well i'm going to write a 2 synchronized method here
so next we need to type....
....
....and I think we've used that
before the course but it's very similar to a system.out.println
the only difference is we pass parameters like this will do...
....and we pass the two
parameters so...
so what happens is when we run this the percent s gets replaced with the
parameters in order so the first %s gets replaced with this.name contents
of the name of field and the second percent s gets replaced with the person
object from the getter which will return the name
string and percent n goes to a new line so I'm using system.format
because it's more likely when we get to the stage of synchronizing or try to run
this you know it's got a higher probability of actually did locking that's why
we're using it out just to sort of simulate how this works but essentially
you could do this with system.out.println
but you probably won't get a deadlock when we go to run so....
....
it's going to be very much the same polite....
we're going to do....and same thing
....
ok so when an object says hello
we want the other object to say hello back before another thread can say hello
to the same object
also we want an object to finish saying hello back to one object before it says
hello back to another object so we synchronized the say hello and say hello
back methods to do that
so now that we've written those methods let's go ahead and create the two
objects and have them to say hello to each other
firstly on the same thread going to come back to our main method and we'll type
....
....but one other thing we'll need
to do after that is in our say hello method i mentioned that time we want the
other object to say hello back
so what we need to do is in our say hello method after the system.out.format
we want to put person which is the object passed to this method as an argument....
....
so it's calling the method in that object and pass this being the current
object back to that
so we're getting another object to say hello back alright so we run this we should
work because we're using the same thread
let's just check that we see the jane says hello to John and then John says
hello back then John says hello to Jane and jane says hello back
and again since all the code is running on the same thread we can't actually
experience a deadlock
but what happens if we have Jane and John say hello to each other on
different threads so to simulate that
or to do that let's actually change this code here we're going to create new
threads so we are going to put...
...and we will paste this first code from Jane
and we will probably have to check mark the variable to type final
because we're using an inner class
the variable needs to be declared final so will just do a final here to keep
intelliJ happy and we'll do the same for John and next what we need to do here we
have to start the thread of course as well not just define it
....start on the end of it and then we'll
come back here and we will paste in the code for John
so essentially what we've done now is we've wrapped the calls to each object
into a thread
so we're now ensuring that they're both running on different threads so will
this work well it will depend on timing when we run it but it'll probably
deadlock
Jane will say hello to John and John will say hello to Jane but neither of them
will probably say hello back
so lets just test that and see what it proves to be the case so you can see that John has
said hello to me so
in other words as i mentioned Jane said hello to John and John you can see on the
second line of output has said hello to Jane but neither of them are saying hello
back and we can try running it again
by stopping at first most cases it should deadlock
there's a chance depending on timing that it will work but you can see I've
tried three times and its a deadlocked each time because that say hello back
hasn't worked so looking at is code or perhaps you're looking at
this now and thinking you know how can this happen
how are both threads able to to enter the say hello method since the
method is synchronized won't one thread block until the other threads finished
executing the method
yes if the threads are calling the method using the same object when we
synchronize on a method a thread has to acquire the intrinsic lock for the
object
it's using to call the method
now in our example two objects are involved
so let's take a look at one possible sequence of execution that may
will lead to the deadlock and what I'm going to do is I'm just going to paste
some text here for each one and then we'll just go through them
and I'll just paste it somewhere on the screen will actually delete this shortly
....
ok so the first scenario that could potentially happen if I just close this
briefly so you can see it
so the very first case what could happen is thread one acquires the lock on the
Jane object and enters the say hello method
it prints to the console then suspends then thread 2 acquire the lock on the John
object
and enters the say hello method it prints to the console then suspends and step three
thread 1 runs again and wants to say hello back to the John object it tries
to call the say hello back method using the John object that was passed into the
say hello method but thread 2 is holding the John Lock so thread 1
suspends and the last step step 4 potentially thread 2 runs again and wants
to say hello back to the Jane object it tries to call the say hello back method
using the Jane object that was passed to the say hello method but thread
1 in this case is holding the Jane Lock so thread 2 suspends so in this
scenario we've got a deadlock and that's actually what's happening in our code
again just to run it will just delete this out now
so if we run it
we're getting that deadlock each time we run it so the potential for deadlocks more
difficult to see here because we're using objects past as parameters so it's
not obvious that we could have multiple threads trying to lock the same objects
but in a different order
now this was obviously a simple example where everything is in one file but if
you think about it imagine an application that uses you know perhaps
hundreds of classes and uses hundreds of threads
it would be very easy for problems like this sneak into the code if we're not
careful
so I hope you can see that once again the deadlock occurs because of the order
in which threads are trying to acquire locks
that's usually the underlying cause of a deadlock
so when synchronizing code always be on the lookout for places where this
situation can arise
so that's it for deadlocking going to finish the video now in the next video
we're going to start talking about a problem that can arise with threads
that's called starvation
see you in the next video