-6
public class SingletonDoubleCheckedLock {
    private volatile static SingletonDoubleCheckedLock uniqueInstance;

    private SingletonDoubleCheckedLock() {
    }

    public static SingletonDoubleCheckedLock getInstance() {
            if (uniqueInstance == null) {
                    synchronized (SingletonDoubleCheckedLock.class) {
                            if (uniqueInstance == null) {
                                    uniqueInstance = new SingletonDoubleCheckedLock();
                            }
                    }
            }
            return uniqueInstance;
    }
}

If any error occurs when running the getInstance() method (e.g. when executing new SingletonDoubleCheckedLock() but there isn't enough memory) and I still want the getInstance() method return the right result. How to achieve this?

pstar
  • 31
  • 5
  • *"If any error occurs then..."* Then what? getInstance() will throw an exception. What exactly is the behavior you expect? – Philipp Dec 14 '13 at 14:59
  • 3
    AFAIK the best way to implement a singleton in Java is through an `enum`. See [this answer](http://stackoverflow.com/a/71399/1825094). – Max Truxa Dec 14 '13 at 14:59
  • If you consider `enum` hacky, the [Spring framework](http://projects.spring.io/spring-framework/) has set up singletons for years. – andi5 Dec 14 '13 at 15:02
  • Is it me, or are you checking one condition two times in a row without doing anything? – Mario Stoilov Dec 14 '13 at 15:12
  • 2 things: 1: your instance does not need to be volatile. 2: you can synchronize the getInstance() method and lose the synchronized block within. Only check for null once. – NickJ Dec 14 '13 at 15:17
  • 1
    @NickJ Making the method synchronized would potentially create a fairly large performance hit if many calls are made to getInstance() simultaneously. Declaring the instance as volatile is also importance and Java's memory model does not handle double-checked locking well: https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java – thesquaregroot Dec 14 '13 at 15:23
  • I am aware that enclosing too much in synchronized blocks is a performance hit, but I stand by my comment because by far the most expensive operation in `getInstance()` is creating the instance, which would need to be synchronized anyway. Checking the existance if relative cheap, and also needs to be in the same synchronised block, so you may as well just synchronize the method. Volatile is unnecessary because `uniqueInstance' is only ever accessed from the same synchronized block. – NickJ Dec 14 '13 at 18:26

1 Answers1

1

Question: "If any error occurs when running the getInstance() method ... and I still want the getInstance() method return the right result. How to achieve this?"

Short answer: you can't guarantee it.

There are a large number of conditions which can throw a Throwable

There are 2 main types (subclasses) of Throwable : Exception and Error.

Exception is used to indicate a condition which may arise in the application to prevent normal flow of execution, and the application may catch and correct the situation before continuing. Some forms of Exception (checked exceptions) have to be caught eventually.

Error is used to indicate a seriously abnormal condition from which the application cannot be expected to recover, the cause of which is probably beyond the application's control. You can catch an Error but there's not much point as the situation probably cannot be recovered.

As you can see, if your getInstance() throws an error, there's nothing you can do whilst the application is running. You only have a sporting chance of recovery if an Exception occurs.

NickJ
  • 9,380
  • 9
  • 51
  • 74