They claim there that the double checked locking is not good because -
Unfortunately, double-checked locking is not guaranteed to work because the compiler is free to assign a value to the singleton member variable before the singleton's constructor is called. If that happens, Thread 1 can be preempted after the singleton reference has been assigned, but before the singleton is initialized, so Thread 2 can return a reference to an uninitialized singleton instance.
however, the astute reader may realize that the getInstance() method only needs to be synchronized the first time it is called. Because synchronization is very expensive performance-wise (synchronized methods can run up to 100 times slower than unsynchronized methods),
Synchronization has gotten much cheaper over the years. Frankly I think that article in 2003 was already rather out-of-date in this area, and now it's more out-of date. Synchronization is not that big a deal, performance-wise, and much convoluted, hard-to-maintain code has been written needlessly by people trying to avoid it.
As for your original question, Java 5 does allow the double-checked locking technique to work correctly, if you mark the variable as volatile. If you don't mark the variable volatile, it's still broken. See this FAQ for more info. And note that they suggest a better way to achieve a lazily-initialized singleton anyway: