Saturday 10 May 2014

The problem with notifyAll() : Introducing Reentrant Locks

Here is a Buffer:

Imaging that you have two producers threads calling 'put(int i)' and one consumer thread calling get().

Imaging the following sequence of events:

- Consumer calls get() and blocks waiting for lock
- Producer1 calls put(int i) and, while it is in the synchronized block, Producer2 starts and also waits for the lock currently held by Producer1. Therefore both the Consumer and Producer2 are waiting.
- Producer2 releases the lock and calls notifyAll()
- The JVM chooses to wake Producer2 first
- Producer2 enters the synchronised block, sees it cannot write and goes back to waiting.
- Then the Consumer gets the lock, enters the block in the get() method and retrieves the variable.
- etc

This is totally functional code but the problem is that the JVM wakes all the threads, both producers and consumers.  This is fine in our example but imagine we had thousands of producers and consumers; suddenly it becomes very inefficient and memory intensive to wake up all the threads, when most of them will just go straight back to waiting because their predicate is not fulfilled.

The solution? Java 5 reentrant locks!

These allow you to have different wait conditions and wake only the threads that are waiting for that particular condition.

The modified solution is shown below:



No comments:

Post a Comment

Scala with Cats: Answers to revision questions

I'm studying the 'Scala with Cats' book. I want the information to stick so I am applying a technique from 'Ultralearning&#...