Getting a deadlock without using any locks
Josh Block and Neil Gafter gave what was in my opinion the most interesting talk of JavaOne, day 1 on coding puzzles.
Some of the puzzles were the kind where the warning signs go off just as soon as you see them, and the sensible thing is to quit trying to work out what is going on, and just change it to be obvious. For example:
count += count++;
Stop thinking about what it does - ask what it should do and re-write it.
count++; count = count * 2;
Is way clearer, and isn't buggy.
The real gem in the list of puzzles was on avoiding the "lock-free dead-lock" scenario. The following code uses a Thread to do some complex initialization for a class in the background:
public class LazySetup { private static boolean init = false; static { Thread t = new Thread(new Runnable() { public void run() { // hard work goes here init = true; } } t.start(); try { t.join(); } catch (InterruptedException ex) { } } public static void main() { System.out.print(init); } }
Apparently there is Swing code that does something similar. You could use an idiom like this to set off an number of setup tasks in parallel; but don't!
The very subtle bug is that the line that says init = true;
. Since this line is executing in a different (inner) class and thread from the main LazySetup class and thread, the JVM needs to check to see the status of the Class to see if it is properly initialized.
Clearly it isn't - The main thread is waiting for the the child thread in the t.join();
line, which is inside the static init block. So before the init = true;
line is executed the JVM stops execution of this thread to wait for the initialization to finish, which of course will never happen.
Outch! The moral is never use lazy threads to initialize your resources, or if you really need to you should create some separate classes so the init order is clearer.
Comments
Comments have been turned off on old posts