Interview: Implementing a Singleton Mode in Java

Source: Internet
Author: User
Tags volatile

interview: Implementing a Singleton mode in Java

After the interview series update, finally ushered in our first phase, we will close to the "sword refers to offer" topic to bring you the explanation of Java, individual or very recommended "sword refers to the offer" as the interview will brush books, this does not, once again to share this book to everyone, the PDF version in the public number backstage reply " offer"can be obtained by means of a sword.

We always encounter a lot of design patterns in the interview problem, and design patterns in the Singleton mode is our most likely to appear in the exam, most people may have been fully understood before, but a lot of people just stay in the more superficial level, today we combine "sword point offer" To bring you more in-depth explanation.

Title: Please write a singleton pattern code in Java and want to consider it as comprehensive as possible.

Whether it's Java or Android, the singleton pattern is definitely something we often use, so this problem may be the first time most people think of a hungry man code.

PublicClasssingleton {
   private Static final singleton INSTANCE = new singleton ();
?
   private singleton () {
 }
?
   public static Singleton getinstance () {
        return instance;
 }
} /span>

The above is a typical a hungry man style, because the singleton instance is declared as static and final variables, so when the first load class into memory will be initialized, so there is no multithreading problem, but its shortcomings are very obvious, but also often criticized. This is obviously not a lazy load mode (lazy initialization), because it is static and final, so the class will be initialized after loading, resulting in poor robustness of our code, if you change the requirements later, we hope getInstance() to Before calling a method to set its parameters, this is obviously not in line with the use of the scene, the interviewer is likely to see this code after you are a only know the completion of the function is not bigger picture people.

Of course, there will be a lot of people directly using our lazy code, which solves the ductility and lazy loading.

PublicClassSingleton {
PrivateStaticSingletonInstance
?
private singleton () {
 }
?
   public static Singleton getinstance () {
       if (instance == null) {
           instance = new singleton ();
     }
       return instance;
 }
?
} /span>

The code above may be the solution for most interviewers, including in textbooks, but there is a fatal problem with this code, which is that when multiple threads are called getInstance() in parallel, multiple instances are created, which clearly violates the interviewer's meaning. Just as the interviewer added a wish to be considered as comprehensive as possible, so the code must not captured the interviewer's heart.

Since it's thread-safe, I'll just lock it up. The following code is then available. They are also lazy, but they are thread-safe.

PublicClassSingleton {
PrivateStaticSingletonInstance
?
PrivateSingleton () {
 }
?
   public static Synchronized singleton getinstance () {
       if (instance == null) {
           instance = new singleton ();
     }
       return instance;
 }
?
} /span>

Such a solution is thread-safe, but it is not so efficient because at any time there can only be one thread to invoke the getInstance() method, but actually the lock operation is time consuming and we should try to avoid using it. So nature leads to a double test lock.

PublicClassSingleton {
PrivateStaticSingletonInstance
?
PrivateSingleton () {
}
?
PublicStaticSingletonGetInstance () {
if (Instance==NULL) {
synchronized (singleton. Class) {
               if (instance == null) {
                   instance = new singleton ();
             }
         
     }
        return instance;
 }
?
} /span>

This piece of code looks perfect, unfortunately, it's problematic. The main reason is instance = new Singleton (), this is not an atomic operation, in fact in the JVM this sentence probably did the following 3 things.

    1. allocating memory to instance

    2. Call Singleton's constructor to initialize member variables

    3. Point the instance object to the allocated memory space (instance is non-null after performing this step)

However, there is an optimization of command reordering in the JVM's immediate compiler. In other words, the order of the second and third steps above is not guaranteed, and the final order of execution may be 1-3-2. If it is the latter, then after 3 execution, 2 is not executed, before the thread two is preempted, then instance is non-null (but not initialized), so the thread two will return directly to instance, then use, and then logically error.

We just need to declare the instance variable to be volatile.

PublicClassSingleton {
PrivateVolatileStaticSingletonInstance
?
PrivateSingleton () {
}
?
PublicStaticSingletonGetInstance () {
if (Instance==NULL) {
synchronized (singleton. Class) {
               if (instance == null) {
                   instance = new singleton ();
             }
         
     }
        return instance;
 }
?
} /span>

Some people think that the reason for use is visibility, which is to ensure that the volatile thread does not have a copy of instance locally, and that it is read in the main memory every time. But it's not right, actually. volatile The main reason for use is another feature: Prohibit command reordering optimizations. That is, volatile There will be a memory barrier (generated assembly code) behind the assignment of the variable, and the read operation will not be reordered before the memory barrier. For example above, the take operation must be executed after 1-2-3 or after the 1-3-2, there is no execution to 1-3 and then fetch the value of the case. From the perspective of the "first occurrence principle", it is that the write operation of a volatile variable takes precedence over the reading of the variable ("Back" is the order of time).

However, it is important to note that there is a volatile problem with double check locks that were used in previous versions of Java 5. The reason is that Java 5 JMM (Java memory model) is flawed, the immediate declaration of variables as volatile does not completely avoid reordering, mainly the volatile variable before and after the code still has a reordering problem. This volatile masking reordering problem is only fixed in Java 5, so it is safe to use after this volatile .

So, is there a simple way to have lazy loading and secure thread safety?

Of course, static internal classes are the kind of method we want. We can put the Singleton instance in a static inner class, which avoids the creation of the static instance when the Singleton class is loaded, and because the static inner class is only loaded once, it is thread-safe.

PublicClassSingleton {
PrivateStaticClassHolder {
       private static singleton instance = New singleton ();
 }
?
   private singleton () {
 }
?
   public static Singleton getinstance () {
        return holder. INSTANCE;
 }
}

This is my recommended solution, which uses the JVM's own mechanism to ensure thread safety, while reading the instance is not synchronized, there is no performance flaw, and does not rely on the JDK version.

Even so, it's important to note that in the 3rd effective Java, it's worth reminding that a privileged client can invoke a AccessibleObject.setAccessible private constructor by means of a reflection mechanism. If you need to defend against this attack, you can modify the constructor so that it throws an exception when it is asked to create a second instance.

"Effective Java Chinese version" PDF in the public number back "effective java" can be obtained.

we actually have a simpler enumeration of the singleton.

People who have used enumerations to write a single case say: It's too easy to write an enumeration with enumerations. the following code is the usual way to declare an enumeration.

easysingleton{
INSTANCE;
}

This is a single-instance approach that can be useful from the Java 1.5 release, which allows us EasySingleton.INSTANCE to access the instances, which is getInstance() much simpler than calling methods. Creating an enumeration is thread-safe by default, so there is no need to worry about double checked locking, and it can prevent deserialization from causing new objects to be recreated. But it is rare to see someone write like this, perhaps because they are not familiar with it.

Summary

A summary is certainly essential, and the above is just a list of our common singleton implementations. Of course not completely, for example, we can also use static code block way to implement the lazy code, but here is not one by one examples.

Personally, I prefer to use the singleton mode in a static inner class, and if it involves deserializing the object, try enumerating

Article Reference link: http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern/

Interview: Implementing a Singleton Mode in Java

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.