Double check mode
public class Singleton { private volatile static Singleton singleton; / / 1: volatile modify privateSingleton (){}
public static Singleton getSingleton() {
if(singleton == null) {//2: synchronized (singleton. Class) {// 3: synchronized, thread safetyif(singleton == null) { singleton = new Singleton(); //4: create singleton object}}}returnsingleton; }}Copy the code
Recommended reasons:
- Delayed initialization. Consistent with the lazy mode, static methods are only called the first time
getSingleton
Is initializedsignleton
Instance. - Performance optimization. Synchronization may cause performance degradation. Therefore, it passes interpretation before synchronization
singleton
Whether to initialize to reduce unnecessary synchronization overhead. - Thread safe. Create the Singleton object synchronously, taking note of the static variables
singleton
usevolatile
Modification.
Why use volatile?
When you create an object in step 4, you have the following pseudocode, even though you already use synchronized:
memory=allocate(); //1: allocate memory space ctorInstance(); //2: initialize object singleton=memory; //3: set the singleton to point to the memory space just sortedCopy the code
While thread A is executing the pseudocode above, reordering of 2 and 3 May occur, which the JVM allows because reordering does not affect the results and can improve performance. If the pseudocode is reordered, the step becomes 1->3->2. When thread A reaches step 3, thread B calls getSingleton, and returns Singleton if it is not null when singleton==null. But the Singleton has not been initialized yet, and thread B will be accessing an uninitialized object. When a reference to an object is declared volatile, reordering of pseudocode 2 and 3 is prohibited in multithreading.
Static inner class pattern
public class Singleton {
private Singleton(){
}
public static Singleton getSingleton() {returnInner.instance; } private static class Inner { private static final Singleton instance = new Singleton(); }}Copy the code
Recommended reasons:
- Implement code brevity. Compared to the double-checked singleton, the static inner class singleton implementation code is really neat and clear.
- Delayed initialization. call
getSingleton
To initialize theSingleton
Object. - Thread safe. During the initialization phase of a class, the JVM acquires a lock that synchronizes the initialization of the same class by multiple threads.
How to achieve thread safety?
Thread A and thread B both attempt to acquire the initializing lock of the Singleton object. Assuming thread A does, thread B waits for the initializing lock. Thread A performs class initialization, and even if the pseudo-code is reordered in double-checked mode, it does not affect the initialization result of thread A. After initialization, the lock is released. Thread B obtains the initialization lock, finds that the Singleton object has been initialized, releases the lock, does not initialize, and obtains the Singleton object.
In singletons involving reflection and serialization, the enumeration type pattern below is recommended.
Other types of singletons
Slob mode (multi-threading unsafe)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
returninstance; }}Copy the code
Han Singleton mode (Multi-threaded safety)
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
returninstance; }}Copy the code
The thread-safety of Han mode also solves the synchronization problem through class loading, but does not achieve lazy loading. (Thank you very much for the correction of Z-Chu at the beginning)
Enumeration singleton mode (multi-threaded safety)
public enum Singleton {
INSTANCE;
public void doSomething(){
//todo doSomething
}
}
Copy the code
This method is recommended in Effective Java by Joshua Bloch. Thread safety, though, has not been widely adopted in actual development. It is too simple to read and has not been widely used in actual combat. Enumeration singleton mode also makes use of the static inner class mentioned in the class initialization lock. The enumeration singleton pattern ensures instance uniqueness in both serialization and reflection.
Master between the fight, must choose enumeration singleton mode.