Singleton pattern with combination of lazy loading and thread safety

前端 未结 5 1878
天涯浪人
天涯浪人 2021-02-03 23:53

I was doing some research about singletons, specifically regarding lazy vs eager initialization of singletons.

An example of eager initialization:

public         


        
相关标签:
5条回答
  • 2021-02-03 23:55

    In my opinion, this is an inappropriate pattern to use. It makes assumptions about the JVM's behavior which are non-trivial and confusing. Also, it has a dummy class. Dummy classes should be avoided when possible.

    I suggest the straightforward approach:

    public class Foo {
        private volatile static final Foo instance = null;
    
        private Foo() {
        }
    
        public static Foo instance() {
            if (instance == null) instance = new Foo();
            return instance;
            }
        }
    }
    

    ... although, this does not work as-is - it's not thread safe.. What you really want is the double-check pattern presented in Item 71 of Bloch's Effective Java; see here. Adapting the example at the link to your case, we get:

    public class Foo {
        private volatile static final Foo instance = null;
    
        private Foo() {
        }
    
        public static Foo instance() {
            if (instance != null) return instance;
            synchronized(instance) {
               Foo result = instance;
               if (instance == null) {
                    result = instance = new Foo();
               return result;
            }
        }
    }
    

    Notes:

    • Don't worry about the performance of this code, modern JVMs take care of it and it's just fine. After all, premature optimization is the root of all evil.
    • As is suggested in other answers, the above is not Bloch's preferred solution, but I think using an enum for a singleton is semantically inappropriate just like what OP did originally.
    0 讨论(0)
  • 2021-02-03 23:57

    You first design is actually lazy. Think about it, the instance is only created when the class is initialized; the class is only initialized when the getSingleton() method is called [1]. So the instance is only created when it's asked for, i.e. it's lazily created.

    [1] http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1

    0 讨论(0)
  • 2021-02-04 00:14

    Your second code snippet is, in my opinion, the best way of thread-safe lazily initializing a singleton. It actually has a pattern name

    Initialization-on-demand holder idiom

    I would suggest you use it.

    0 讨论(0)
  • 2021-02-04 00:18

    The best way is actually to use the Enum Way:

    public enum Singleton {
        INSTANCE;
        public void execute (String arg) {
                //... perform operation here ...
        }
    }
    
    0 讨论(0)
  • 2021-02-04 00:22

    The second one is very bad in terms of readability, first one is suitable. Have a look at this article. Its about double check locking, but also will give you wide information about singletons multithreading.

    0 讨论(0)
提交回复
热议问题