I recently introduced a deadlock into our performance monitoring. I inadvertently prevented a statistic collection daemon I wrote from shutting down thanks to some unlucky timing and a bad synchronisation policy. Because the synchronisation that was involved was distributed across a couple of classes (including some external classes) it wasn’t obvious where they clashed. It got me thinking more about deadlocks and how many times we actually see them in real systems. In the end, I created a
I’m talking here about Java level deadlocks and to illustrate the point, poor old
Nibbles got himself into quite a pickle. The situation is like this;
Nibbles has been abducted and the
Negotiator threads have started a dialogue.
However, in the process of negotiation it becomes apparent that the
Kidnapper is unwilling to release poor
Nibbles until he has received the
Cash and the
Negotiator is unwilling to part with the
Cash until he has poor
Nibbles back in his arms.
By synchronising on nibbles below, the
Kidnapper is holding onto him (more specifically his monitor) until the end of the synchronised block. However, within this block the
Kidnapper is trying to take the cash. The access to this method is itself synchronised on the cash, meaning that no one else can access the cash whilst the
Kidnapper is grabbing it. Meanwhile, the
Negotiator is synchronising on the cash, holding onto it (or again, more specifically, it’s monitor) until the end of the synchronised block then within that block, it requires nibbles. We can start to see the potential for deadlock.
The deadlock detector displays this woeful situation as follows.
Deadlock detected ================= "Negotiator-Thread-1": waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cat@ce4a8a which is held by "Kidnapper-Thread-0" "Kidnapper-Thread-0": waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cash@7fc8b2 which is held by "Negotiator-Thread-1"
If you fire up the example and point jconsole at it, you’ll get similar results from the Thread tab. You can see how tempus-fugit tests the
DeadlockDetector class here and to find out more about see the project documentation.
Oh and don’t worry,
Nibbles was released and the
Kidnapper arrested in the end.