there are 2 threads in the example. Let’s name them ThreadA and ThreadB.
e.g. in time order this could happen:
ThreadA: a.bow(g)
ThreadB: g.bow(a)
ThreadA: g.bowBack(a) - blocked as g is busy with ThreadB from the previous line.
ThreadB: a.bowBack(g) - blocked as a is busy with ThreadA from the first line.
ThreadA and ThreadB are now both blocked, i.e. deadlocked
The synchronized keyword works on methods per object instance…
I really liked the example that was given to me at university, called “dining philosophers”.
The idea is that you have a round table with philosophers that most of the time just think, but from time to time they have to eat. To that end they each have a plate with food, and there are forks between each two philosophers (so there are as many forks as philosophers). When a philosopher wants to eat, he needs to have both the fork on his left, and the one on his right (it’s not good manners to with just one fork). So obviously when a philosopher is eating, the philosopher to his left, and the one to his right, can’t (because they both only have one fork each, at most).
Now, even though it’s not allowed to eat with one fork, it is allowed to pick up one fork when it’s free, and then wait for the second free to become available. When they have one fork though, they don’t put it down until they have the other one as well.
Now, imagine that at one point all philosophers pick up one fork at the same time. At that point they are all waiting for a second one, but they will never come, because they are all waiting for it, and no more forks are available. So essentially everyone is waiting for everyone and the situation will never ever resolve itself.
That, is deadlock
Edit:
I see now that you already know what it is, my bad. Oh well, hope you enjoy my little story nonetheless
It isn’t, g.bowBack(a) is the 3rd thing that happened, a.bow(g) is the 1st.
Here’s a more detailed explanation… first line happens first:
ThreadA enters a.bow(g) - ThreadA locks a
ThreadB enters g.bow(a) - ThreadB locks g
ThreadA attempts to enter g.bowBack(a) - but ThreadB already locked g in the previous line. ThreadA is now blocked and waiting.
ThreadB attempts to enter a.bowBack(g) - but ThreadA already locked a in the first line. ThreadB is now blocked and waiting.
Yes, threads take turns to run and you should consider they will happpen in random order. e.g. this could also happen, with no deadlock issue:
ThreadA enters a.bow(g) - ThreadA locks a
ThreadA enters g.bowBack(a) - ThreadA locks g
ThreadB attempts to enter g.bow(a) - but ThreadA already has a lock on g from the previous line. ThreadB is now blocked and waiting for g to be released.