Step by Step knowledge Point induction, the former indefinitely, understand the surface, know a bit do not know the knowledge of the surface of the document. Lazy Single-case:privatisation constructor, block outside instance Session object, callGetInstance static method to determine if it has been instantiated. Why lazy, because it belongs to the lazy loading of this instance, that is, when not in the time, do not instantiate the object.
Public class Singleton { privatestatic Singleton instance; Private Singleton () {} Public Static Singleton getinstance () { ifnull) { new Singleton (); } return instance;} }
Thread safety issues: when multithreading simultaneously calls the GetInstance () method, while judging the instance, into the instantiation of the operation, simple interest no longer exist.
For thread safety, we synchronize the GetInstance () method:
Public class Singleton { privatestatic Singleton instance; Private Singleton () {} Public Static synchronized Singleton getinstance () { ifnull) { new Singleton (); } return instance;} }
The synchronized modifier guarantees that only one thread at a time can execute the GetInstance method, which guarantees the thread safety of the singleton. However, the synchronization granularity seems to be too large, in fact, we do not need to ensure that each thread queue to take this instance after initializing the instance.
Then the code for double-checking the lock is introduced:
Public classSingleton {Private StaticSingleton instance; PrivateSingleton () {} Public StaticSingleton Getsingleton () {if(Instance = =NULL) {//Single Checked synchronized( This) { if(Instance = =NULL) {//Double CheckedInstance =NewSingleton (); } } } returninstance; }}
Synchronize fast out and inside check two times to ensure that the thread entering the synchronization block does not produce a new instance.
When multiple threads are concurrency, it is determined that the instance is null to start the competition lock, where one thread takes the lock to instantiate the operation, while the other threads need to wait, while the instantiated thread frees the post, and then the incoming thread does not determine whether the singleton has been produced, then it will instantiate an object, so it cannot implement the singleton. This double check lock is turned on for perfection, and command reordering can cause problems. I think this is also a good example of learning reordering.
New Singleton ();
The above code is not an atomic operation, i.e. it cannot be translated into an instruction complete.
It is done by a few 3 instructions:
Assign memory to instance to call Singleton's constructor to initialize the member variable to point the instance object to the allocated memory space address
The command reordering of the JVM at compile time may disrupt the execution order of the above three instructions, that is, it is possible to go straight to 1,3 and then execute 2. So there is a situation when the execution of good 1 and 3,instance is not NULL, the newly entered thread will return an instance that does not perform the 2 step directly when judging the first null, so there is no expectation. This is indeed a classic scene.
Additional Reading
If we take the third step and write it separately after the instance is initialized, it seems to solve the problem with the following code:
Public StaticSingleton getinstance () {if(Instance = =NULL) { synchronized(Singleton.class) {Singleton temp=instance; if(temp = =NULL) { synchronized(Singleton.class) {Temp=NewSingleton (); } instance=temp; } } } returninstance; }
The volatile keyword is actually a barrier to re-ordering at compile time. Specific individual statements can be read in the following article:
Extended Reading
From the above can be felt, in the cumulative load when the initial good instance, there will be many things to consider, then if the compilation phase of the good instantiation, so you can avoid the problems caused by concurrency.
That is the so-called a hungry Man single-case:
Public class singleton{ // class loads when the privatestaticfinalNew is initialized Singleton (); Private Singleton () {} Public Static Singleton getinstance () { return instance; }}
Of course, this naturally has its own drawbacks, that is, the singleton is not used in the time it has to be instantiated, so it will occupy unnecessary memory, if the instance initializes complex resource utilization, and the actual may not be used is more embarrassing.
In other words, this instantiation of the method will not implement a scenario that relies on external parameter instantiation.
The
also has a recommended notation:
public class Singleton { static class Singletonholder { Span style= "color: #0000ff;" >private static final Singleton INSTANCE = new Singleton (); private Singleton () {} public static final Singleton getinstance () { return Singletonholder.instance; }}
There is also a master recommendation of the wording, there is no very tall on:
Public enum easysingleton{ INSTANCE;}
Let's take a look at how to break a single example:
1, serialization and deserializationOf course, the code we wrote earlier does not require serialization and deserialization, and there is no problem, just saying that we consider how to destroy it in this regard, as in the following example:
Public classSingletonImplementsserializable{Private volatile StaticSingleton Singleton; PrivateSingleton () {} Public StaticSingleton Getsingleton () {if(Singleton = =NULL) { synchronized(Singleton.class) { if(Singleton = =NULL) {Singleton=NewSingleton (); } } } returnSingleton; }} Public classSerializableDemo1 {//for ease of understanding, the close stream operation and the delete file operation are ignored. Don't forget the real code .//Exception Direct Throw Public Static voidMain (string[] args)throwsIOException, ClassNotFoundException {//Write Obj to fileObjectOutputStream Oos =NewObjectOutputStream (NewFileOutputStream ("Tempfile")); Oos.writeobject (Singleton.getsingleton ()); //Read Obj from FileFile File =NewFile ("Tempfile"); ObjectInputStream Ois=NewObjectInputStream (Newfileinputstream (file)); Singleton newinstance=(Singleton) ois.readobject (); //determine if it is the same objectSystem.out.println (newinstance = =Singleton.getsingleton ()); }}//false
2, Reflective
Public classSingleton { Public Static FinalSingleton INSTANCE =NewSingleton (); PrivateSingleton () {} PublicSingleton getinstance () {returnINSTANCE; } Public Static voidMain (string[] args)throwsException {//reflection mechanism destroys a single case modeClass clazz = Singleton.class; Constructor C=Clazz.getdeclaredconstructor (); //The reflection mechanism allows private methods to be accessed!!! C.setaccessible (true); //determines whether the reflection-generated object is equal to the singleton objectSystem.out.println (Singleton.instance = =c.newinstance ()); }}
The principle of destroying a singleton is that you can generate an instance without taking the constructor, because we only close the constructor.
At this point, the Java Singleton has a more comprehensive understanding, involving a large number of knowledge points, need to continue to dig.
Let's move on
----------------------------------------------------------------------
Effort is not necessarily successful, but not effort will not succeed.
Java single example-building blocks series