Java Singleton mode

Source: Internet
Author: User

On the single-case model of the article, in fact, the internet has already flooded. But in a small single case, there are many changes in it. Most of the articles on the Internet are also mentioned in one or several points, there are few more comprehensive and clear-text article, so I began to write the idea of this article. Try to say this single case thoroughly, say in depth. I wish I didn't do too badly.

Let's start with a typical implementation:

/*** Basic singleton mode, lazy mode, non-thread safe * Advantages: lazy, instantiate Singleton on first use, avoid resource waste * Disadvantage: 1, lazy, if the instance initialization is very time-consuming, initial use, may cause performance problems * 2, non-thread-safe. Multiple instances may be initialized under multithreading. *  * @authorLaichendong *@since2011-12-5*/ Public classSingletonone {/**Singleton Example Variable*/    Private StaticSingletonone instance =NULL; /*** Privatization of the construction method, to ensure that the external class cannot be instantiated by the constructor. -*/    PrivateSingletonone () {}/*** Get an instance of a singleton object * *@returnsingle-instance object*/     Public StaticSingletonone getinstance () {if(Instance = =NULL) {//1Instance =NewSingletonone ();//2        }        returninstance; }    }

There is already a simple analysis in the comments. Next, analyze the section on "Non-threaded security."

1. When thread a enters line 28th (#1), check if instance is empty and empty at this time.
2. At this point, thread B also enters the 28 rows (#1). Switch to thread B execution. The same checks that instance is empty, then executes 29 rows (#2), creating an instance. Then came back.
3. After switching back to thread A, instance is empty because it was previously checked. So 29 rows (#2) are also executed to create the instance. Return.
4. So far, two instances have been created, which is not what we want.

How do I fix a thread safety problem?

  method One: the synchronization method. that is, add the synchronized keyword to the getinstance () method. Then the single case becomes

a singleton using the synchronization method/*** copyright©sf-express INC*/ PackageCom.something.singleton;/*** Synchronization method of the singleton mode, lazy mode, thread safety * Advantages: * 1, lazy, the first time to instantiate a single case, to avoid wasting resources * 2, thread safety * Disadvantage: * 1, lazy, if the instance initialization is very time-consuming, initial use, may cause performance problems * 2, each call GetInstance () to obtain a synchronous lock, performance consumption. *  * @authorLaichendong *@since2011-12-5*/ Public classSingletontwo {/**Singleton Example Variable*/    Private StaticSingletontwo instance =NULL; /*** Privatization of the construction method, to ensure that the external class cannot be instantiated by the constructor. */    PrivateSingletontwo () {}/*** Get a Singleton object instance * Synchronization method to achieve thread-mutually exclusive access to ensure thread safety. *      * @returnsingle-instance objects*/     Public Static synchronizedsingletontwo getinstance () {if(Instance = =NULL) {//1Instance =NewSingletontwo ();//2        }        returninstance; }    }

Plus synchronized it does implement a mutually exclusive access to the thread getinstance () method. This ensures thread safety. But is this perfect ? Let's see. In fact, in the typical implementation , the problem is only when the instance has not been instantiated, the number of threads to access the code # # will cause problems. And when instance has been instantiated, it is done. Each call to getinstance () is actually returned directly. Even if multiple threads are accessed, there is no problem. But after adding synchronized to the method. All calls to the getinstance () are synchronized. In fact, we just need to synchronize the first call. Synchronization needs to consume performance. that's the problem.

  Method two: Double check plus lock double-checked locking.
  
In fact, the analysis found that we just guarantee instance = New Singletonone (), the thread is mutually exclusive access to ensure that thread security. The synchronization method is modified, only with synchronized block parcel this sentence. You get the following code:

 Public Static Singletonthree getinstance () {        ifnull//  1            synchronized (Singletonthree.  Class) {                new//  2            }        }          return  instance;    }

Is this method feasible? Analysis of the discovery is not possible!
1. Thread A and thread B enter the//1 position at the same time. At this point the instance is empty.
2, thread A enters synchronized block, creates instance, thread B waits.
3, thread A returns, thread B continues to enter synchronized block, create instance ...
4. At this time, two instances have been created.

In order to solve this problem. We need to check whether instance is instantiated before//2. ( double check plus lock ) Next, the code becomes:

 Public StaticSingletonthree getinstance () {if(Instance = =NULL) {//1            synchronized(Singletonthree.class) {                if(Instance = =NULL) {instance=NewSingletonthree ();//2                }            }        }        returninstance; }

Thus, when thread a returns and thread B enters the synchronized block, it checks to see if the instance instance is created, and the instance has been created by thread A. So thread B no longer creates an instance, but returns directly. looks like! so far, this problem has been solved by us perfectly. Unfortunately, that is not the case at all! This method is not guaranteed to work well on both single-core and multi-core CPUs. The reason this method failed is the memory model of the current Java platform. There is a mechanism in the Java Platform memory model called "unordered write" (Out-of-order writes). It is this mechanism that causes the failure of the double-check locking method. The key to this problem is on line 5th of the above code: instance = new Singletonthree (); This line actually does two things: 1, calls the constructor method, creates an instance. 2. Assign this instance to the instance instance variable. The problem is that these two-step JVMs are not guaranteed to be sequential. Other words. It is possible that the instance has been set to non-empty before the constructor method is called. Let's look at the process of the problem:
1. Thread A enters the getinstance () method.
2, because at this time instance is empty, so thread a enters synchronized block.
3. Thread A executes instance = new Singletonthree (), and the instance variable instance is set to non-null. (Note that the constructor method is actually called before.) )
4, thread A exits, thread B enters.
5. Thread B Checks if instance is empty and is not empty at this time (the third step is set to non-null by thread a). Thread B Returns a reference to instance. (The problem arises when the instance reference is not an instance of Singletonthree because the constructor method is not called.) )
6, thread B exits, thread a enters.
7, thread A continues to call the construction method, completes the initialization of the instance, and then returns.

Well, keep trying to solve the problem caused by "disorderly writing".

 Public StaticSingletonthree getinstance () {if(Instance = =NULL) {             synchronized(Singletonthree.class) {//1Singletonthree temp = instance;//2                if(temp = =NULL) {                    synchronized(Singletonthree.class) {//3temp =NewSingletonthree ();//4} instance= temp;//5                }            }        }        returninstance; }

Explain the execution steps.
1. Thread A enters the getinstance () method.
2. Because instance is empty, thread A enters the first synchronized block of position//1.
3. Thread A executes the code of Location//2 and assigns the instance to the local variable temp. Instance is empty, so temp is also empty.
4, because temp is empty, thread A enters the second synchronized block of position//3.
5, thread A execution location//4 code, the TEMP is set to non-empty, but has not yet called the construction Method! ("unordered write" issue)
6, thread A is blocked, thread B enters the getinstance () method.
7, because instance is empty, thread B tries to enter the first synchronized block. But because thread a is already inside. So I can't get in. Thread B is blocked.
8. Thread A activates, and continues executing the code for location//4. Call the constructor method. Build the instance.
9. Assign the instance reference of temp to instance. Exit two synchronized blocks. Returns an instance.
10, thread B activated, enter the first synchronized block.
11, thread B executes the code of the location//2, assigns the instance instance to the TEMP local variable.
12, thread B determines that the local variable temp is not empty, so skip the IF block. Returns a instance instance.

OK, the problem is finally solved, the thread is safe. But our code changed from the original 3 lines of code to a big lump of the present. Then there is the following method.

  Method Three: Initialize the static variable beforehand.

/*** Pre-initialized static variable singleton mode non-lazy thread safety * Advantages: * 1, thread safety * Disadvantages: * 1, non-lazy loading, if the construction of a single case is very large, the construction and delay in use, will lead to waste of resources. *  * @authorLaichendong *@since2011-12-5*/ Public classSingletonfour {/**single-instance variable, static, initialized at class load time to ensure thread safety*/    Private StaticSingletonfour instance =NewSingletonfour (); /*** Privatization of the construction method, to ensure that the external class cannot be instantiated by the constructor. */    PrivateSingletonfour () {}/*** Get an instance of a singleton object * *@returnsingle-instance objects*/     Public StaticSingletonfour getinstance () {returninstance; }    }

Seeing this method, the world has become more and more pure. Because of the Java mechanism, static member variables are initialized only once when the class is loaded, and class loading is thread-safe. So the single example implemented by this method is thread-safe. But this method sacrifices the lazy character. The Singleton class is instantiated when it is loaded. As noted in the note: non-lazy loading, if the construction of the single case is very large, the construction and delay in use, will lead to waste of resources.

is there a perfect way to do that? Lazy loading, thread-safe, simple code.

Method Four: use an inner class .

/*** Singleton mode based on inner class Lazy thread safety * Advantages: * 1, Thread safety * 2, Lazy * Disadvantage: * 1, to be found * *@authorLaichendong *@since2011-12-5*/ Public classsingletonfive {/*** Internal class for implementing the Lzay mechanism*/    Private Static classsingletonholder{/**single-Case variables*/        Private Staticsingletonfive instance =Newsingletonfive (); }        /*** Privatization of the construction method, to ensure that the external class cannot be instantiated by the constructor. */    Privatesingletonfive () {}/*** Get an instance of a singleton object * *@returnsingle-instance objects*/     Public Staticsingletonfive getinstance () {returnsingletonholder.instance; }    }

Explain, because the Java mechanism stipulates that the inner class Singletonholder is loaded (and lazy) only when the getinstance () method is first called, and its loading process is thread-safe (thread-safe implementation). An instance is instantiated once when the inner class is loaded.

Finally, summarize:
1, if the Singleton object is not big, allow non-lazy loading, you can use method three.
2, if you need lazy loading, and allow a part of the performance loss, you can use method one. (officials say the current high-synchronized is already relatively fast.)
3, if you need lazy loading, and not afraid of trouble, you can use method two.
4, if need lazy loading, no and! It is recommended to use method four.

Original: http://www.cnblogs.com/coffee/archive/2011/12/05/inside-java-singleton.html

Java Singleton mode

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.