Monday, August 20, 2012

Correct singleton implementation

This is a bit outdated problem, but for my easy reference and for those who haven't stumbled on this problem I decided to write short article about correct singleton implementation. Much longer and descriptive article can be found here.
   It is quite common to see singleton implementation like this:

public class DBConnection {

    private static DBConnection instance;
    
    private DBConnection() {
        //DO something
    }
    
    public static final DBConnection getInstance() {
        
        if (instance == null) {
            instance = new DBConnection();
        }
        
        return instance;
    }    
}

Unfortunately this code doesn't work in multi threaded environment. Sometimes people try to fix it with following code:

public static final DBConnection getInstance() {
        
        if (instance == null) {
            synchronized (instance) {
                instance = new DBConnection();
            }
        }
        
        return instance;
}

This also doesn't work, due to Java memory model. There are some thread safe implementation, which actually differ between Java 1.4 and 1.5 up. For Java 1.4 the correct (lazy) implementation is:

public class DBConnection {

    private static class DBConnectionHelper {
        static DBConnection instance = new DBConnection();
    }
    
    private DBConnection() {
        //DO something
    }
    
    public static final DBConnection getInstance() {
        return DBConnectionHelper.instance;
    }    
}

Non lazy implementation for Java 1.4:

public class DBConnection {

    private static DBConnection instance = 
                           new DBConnection();
    
    private DBConnection() {
        //DO something
    }
    
    public static final DBConnection getInstance() {
        return instance;
    }    
}

From Java 1.5 up, there is available other implementation:

public class DBConnection {

    private static volatile DBConnection instance = null;
    
    private DBConnection() {
        //DO something
    }
    
    public static final DBConnection getInstance() {
        if (instance == null) {
            synchronized (this) {
                if (instance == null) {
                    instance = new DBConnection();
                }
                
            }
        }
        return instance;
    }    
}

And from Java 1.5 singletons can be implemented using enum:

public enum DBConnection {

    instance;
    
    private DBConnection() {
        //DO something
    }    
}

The instance is then accessible following way:

DBConnection connection = DBConnection.instance;




No comments:

Post a Comment