Deadlock quiz… the answer

If you have not yet read it, lets go and check the piece of code causing a deadlock.

In order to not spoling the fun, I’m providing the answer in the full post.

Here’s the code again, so you don’t need to jump between both posts:

public class Singleton implements Runnable {
  public static final String A_STRING = "Hello World".toLowerCase();

  public static final Singleton INSTANCE = new Singleton();

  public static Singleton getInstance() {
 	return INSTANCE;
  }

private Singleton() {
 	super();
 	launchThread();
 }

public void launchThread() {
 	synchronized (this) {
 		Thread t = new Thread(this);
 		t.start();
 		while (t.isAlive()) {
 			try {
 				wait(100);
 			} catch (InterruptedException e) {
 				// Interrupted.
 			}
 		}
 	}
 }

public void run() {
 	System.out.println(A_STRING);
 }

public static void main(String[] args) {
 Singleton.getInstance();
 }
}

This code basically calls a thread from its static initialization. This thread then tries to access some other static data on the class (A_STRING).

That’s the cause of the problem. Class initialization can only happen in one thread, so the second thread can not access A_STRING until the class is fully initialized. As pointed on the comments of the previous post, this does not happen with constant values, only when there’s a method call involved.

So the thread is waiting for the class to initialize.

The other side of the deadlock is the code in the launchThread which is waiting for the thread to end before exiting. Since the thread is waiting for the static initialization to finish, it never terminates and the static initialization never ends… and we have a deadlock.

Now, you might be wondering…

how could you think of such a complicated thing?

Well, it was in some code I was refactoring at work. It used to work extremely well… until I added a log4j logger with:


private static final Logger logger =
    Logger.getLogger(Singleton.class);

There it is, a static initialization with a method invocation. And the thread tried to use it, of course…

This is how a working code can be broken by an (apparently) safe change… So learn from my mistakes, be careful and be sure to have unit tests at hand.

About these ads

  1. Erle Czar Mantos

    :D Nice puzzle … couldn’t have figured it out myself.

  2. Brice

    Wow, I only thought about the other end of the deadlock, however it never cross my mind that class initialization was done in a single thread (however when said it just makes sense).






Follow

Get every new post delivered to your Inbox.

%d bloggers like this: