From Head First design patterns book, the singleton pattern with double checked locking has been implemented as below:
public class Singleton {
Well, there's no double-checked locking for performance. It is a broken pattern.
Leaving emotions aside, volatile is here because without it by the time second thread passes instance == null, first thread might not construct new Singleton() yet: no one promises that creation of the object happens-before assignment to instance for any thread but the one actually creating the object.
volatile in turn establishes happens-before relation between reads and writes, and fixes the broken pattern.
If you are looking for performance, use holder inner static class instead.