Single-Case Design method:
First: Non-lazy loading of singleton classes
public class Singleton {
Private Singleton () {}
Private static final Singleton instance = new Singleton ();
public static Singleton getinstance () {
return instance;
}
}
Second type: synchronous lazy loading
public class Singleton {
private static Singleton instance = NULL;
Private Singleton () {}
public static synchronized Singleton getinstance () {
if (instance = = null) {
Instance = new Singleton ();
}
return instance;
}
}
The third type: Dual detection synchronous delay loading
In order to deal with the original non-lazy loading method bottleneck, we need to check the instance for a second time to avoid excessive synchronization (because the synchronization here only needs to be synchronized when the instance is first created, and once it is created, it does not need to acquire the lock when the instance is acquired), but it does not work in Java. Because if (instance = = null) Outside of the synchronization block, you may see an instance that already exists but is not complete. JDK5.0 later versions are possible if instance is volatile:
public class Singleton {
Private volatile static Singleton instance = NULL;
Private Singleton () {}
public static Singleton getinstance () {
if (instance = = null) {
Synchronized (Singleton.class) {//1
if (instance = = NULL) {//2
Instance = new Singleton ();//3
}
}
}
return instance;
}
}
The problem of double detection locking failure is not attributed to the implementation bug in the JVM, but rather to the Java platform memory model. The memory model allows so-called "unordered writes", which is also a major cause of failure.
To demonstrate the occurrence of this event, assume that the code line instance =new Singleton (); The following pseudo-code was executed:
MEM = allocate (); Allocates memory space for a singleton object.
instance = mem; Note that the instance reference is now non-null but not yet initialized
Ctorsingleton (instance); Calling constructors for Singleton objects through instance
This pseudo-code is not only possible, but is actually happening on some JIT compilers. The order of execution is reversed, but given the current memory model, this is also allowed to occur. This line of the JIT compiler is just a matter of academic practice for locking double checks.
However, since JAVA2, the JMM has undergone a fundamental change, allocating space, initializing, calling the construction method only to complete the working store of the thread, without
When you copy assignments to the primary store, the process is absolutely not visible to other threads. And this field is copied to the main memory area of the process, and there is no space to allocate
There is no possibility of initializing or calling a constructor method. In Java, everything is copied by the value referenced. Synchronizing to the primary store is actually the thread that's working
This constructed object of the store has a compressed heap address value that is copied to the primary store. This process is for other threads, either resource
Is null, or is a complete object. Never put an object that has been allocated space but not constructed so that other threads are visible.
Fourth: Double detection with threadlocal repair
With Threadlocal, the critical resource (the resource that needs to be synchronized) is localized, specifically in this case, the first layer detection condition of the double detection if (instance = = NULL) is converted to the thread local scope. The threadlocal is also used only as a marker to indicate whether each thread has been visited, and if so, it is no longer necessary to walk the synchronization block, which increases the efficiency. But threadlocal was slower in versions before 1.4, but it was safe compared to volatile.
public class Singleton {
private static final ThreadLocal perthreadinstance = new ThreadLocal ();
private static Singleton Singleton;
Private Singleton () {}
public static Singleton getinstance () {
if (perthreadinstance.get () = = null) {
Each thread will be called the first time
CreateInstance ();
}
return singleton;
}
private static final void CreateInstance () {
Synchronized (Singleton.class) {
if (singleton = = null) {
Singleton = new Singleton ();
}
}
Perthreadinstance.set (perthreadinstance);
}
}
Fifth: Lazy loading using internal classes
In order to really delay the load, double detection in Java is not feasible, so only with the help of another class loading plus lazy loading:
public class Singleton {
Private Singleton () {}
public static class Holder {
There's no point in being private here.
/* Private */static Singleton instance = new Singleton ();
}
public static Singleton getinstance () {
Private variables that the perimeter class can access directly to the inner class (whether static or not)
return holder.instance;
}
}
Source: < singleton mode and dual detection-design mode-Java-iteye forum >
From for notes (Wiz)
Java Concurrency 4-Single Instance design method